-
Notifications
You must be signed in to change notification settings - Fork 171
Win32 test std #1090
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Win32 test std #1090
Conversation
I put this back like it was. Changes will be split into smaller parts and I've gotten confused when permissions went back and forth
Update test_std.js
getting back to original codebase
modifies std_tmpfile to work properly with MINGW (I think MSVC will work okay) std_file finalizer modified creates os_symlink for win32
moved a time issue out of WIN32 section. I moved os.symlink out as well and commented, you need admin rights or a setting to execute. test works now with these changes in Windows 11.
I keep seeing "we're all done". Great! I don't know if I'm supposed to leave this branch in place or merge it in my main. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as the other PR, can you fix the style issues first? Thanks.
Sure! I'll also pull out all of the comments and flags. |
... okay, sorry, I took out more than comments. I had some printf functions left in there! I think that warrants some testing, that I didn't see that printf! The reason I didn't see that printf was that windows 10 requires admin rights to test symlinks, and I have it disabled in the test script. I've left a documented flag in test_std.js and properly tested this again. MING64, CLANG64, MSVC, ClangCL with VC Build
const IS_WIN_ADMIN_TEST_FLAG = 0; modified so that someone can run as admin with this flag on and actually test symlink. comment above that clarified that "this code is broken". - That's not my code, my code makes the majority of the std_file finish executing. I just can't readlink from windows , and I can't do that mtime. ...... (but I don't need metric time, I'm not a scientist!
*space*
I didn't think I'd get to it tonight, but I've cleaned these files up. (just the tmpfile/symlink files) I don't know if you'd seen this, I had printf's still in the code for symlink.. That was the whole point of even fixing symlink in windows. I don't need it! I just wanted to see the test scripts complete. I might use tmpfile more. Also, and I'm asking this. maybe I should post a bug discussion? The line before symlink, testing mtime, reports -1000 and expects 10000 or something on all 4 or my windows builds. That's broken too, and that's not something I immediately knew how to fix. So I've bypassed it in the test but it used to be there. I can get to it in the future if it's fixable, but I need this functionality updated so that I can use Quickjs to run my compiles and detect error codes and link my modules for me. I'm doing things the hard way for now! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments, PTAL.
quickjs-libc.c
Outdated
@@ -1034,6 +1034,14 @@ typedef struct { | |||
bool is_popen; | |||
} JSSTDFile; | |||
|
|||
#if defined(__MINGW32__) || defined(__MINGW64__) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't support the old MinGW32 so you can drop that part of the test.
quickjs-libc.c
Outdated
typedef struct { | ||
FILE *f; | ||
int is_kind; | ||
char filename[64]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use JS__PATH_MAX to be safe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is using the tmp environment path size and malloc ... but I'm glad you told me about this. I can use that for os.exec command line buffer size?
quickjs-libc.c
Outdated
#if defined(__MINGW32__) || defined(__MINGW64__) | ||
typedef struct { | ||
FILE *f; | ||
int is_kind; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use an enum to be more readable please.
quickjs-libc.c
Outdated
env = getenv("TEMP"); | ||
int i = 0; | ||
if (env) { | ||
while (env[i]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make the buffer long enough or malloc it, this feels wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
now that you mention it, since I've gone to the trouble of a special destructor, malloc is the right answer. The first time around I was using a different function that handled deleting the file, but then something else was wrong with that solution. I'm glad Bill Gates is gone!
everyone's looking for a solution to this problem, it's actually not easy to get working. (that link wasn't what I thought). I maybe should be detecting the _WIN32 flag here because I'm not sure if Mingw in linux is going to to compile the wrong code here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey sir! do you suggest using malloc? or do you suggest using js_malloc? I was afraid of thrashing the JS memory but I didn't know if there's concerns with the application or the memory management that requires js_malloc.
quickjs-libc.c
Outdated
} | ||
char* fname = &s->filename[i]; | ||
char* templ = "\\qXXXXXXX"; | ||
while (templ[0]) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
memcpy?
@@ -1207,6 +1224,63 @@ static JSValue js_std_fdopen(JSContext *ctx, JSValueConst this_val, | |||
} | |||
|
|||
#if !defined(__wasi__) | |||
#if defined(__MINGW32__) || defined(__MINGW64__) | |||
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, why are we doing all of this when MinGW already has tmpfile
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because it has been broken for years. It's hit and miss with microsoft compilers, because the internal windows code that MINGW calls is still there and that doesn't work. I researched it. It's a folder permission change in the operating system, in at least back to win10. None of my windows versions could run the test_std.js file because of that and the mtime problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the problem? msys2/MINGW-packages#18878 (comment)
Perhaps it's time to default to the UCRT build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pretty clean now. I just tested all 3 builds and there's no compiler warnings. I wouldn't do that!
The whole reason I am on this project helping get your code in order is this:
I followed Node before it was Node.js. Has it been 20 years? Then the Google team had me registering with Google Code. Then I had to do this Clang Build with the MS tools. The requirements became too strict, and then I had to use their custom build scripts. They broke with everything I had. They would not support Mingw and Clang64 on Msys2. It used to work! I have other software that would not support the UCRT, so I can't do both.
@@ -3072,12 +3146,25 @@ static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, | |||
JS_FreeCString(ctx, target); | |||
return JS_EXCEPTION; | |||
} | |||
#ifdef _WIN32 | |||
int isdirflag = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this used for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well you need to tell me if you want the comment or how you want it documented. it is a flag that can be passed if you want to create a directory link. Above the function I commented:
/* in WIN32: (0 | err) os.symlink(target, linkpath, bool isDirectory)
@ msdn: linkpath and target have reversed meaning than symlink! */
The line below it was supposed to be: err = CreateSymbolicLinkA(linkpath, target, ( isdirflag | 2 ) ) ;
but I thought it was a flag. I took it out. I tested that manually before and didn't add folder symlink testing to test_std.js
To be honest it should also have a comment: 1 = SYMBOLIC_LINK_FLAG_DIRECTORY if it's left in there.
Also there probably should also be testing added to test_std.js for folders. It will create a broken link and I didn't get readlink working.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say we can leave directories out (or stat and check if it's a directory and do the right thing without pushing the responsibility to the user)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you want the symlink taken out, it's not exactly the same and error prone in windows. I don't need it. It's more of a shortcut I think, and it doesn't warn you if the path isn't real or anything. You have to be an admin to use it. I just wanted to run test_std.js and get it to finish.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's a shortcut, and fopen doesn't even work on it. I don't know if it's worth it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've left the change request. Is that for this?
I programmed it as an optional parameter, so if a user doesn't specify the flag parameter, it then it still creates a file link by default. I will actually use this, for instance, when I download the current release and link test262 (rather than copy 2GB). Windows users are used to this restriction honestly. To me, qjs could be a first class admin tool.
quickjs-libc.c
Outdated
if (argc > 2) { | ||
if (JS_ToInt32(ctx, &isdirflag, argv[2])) return JS_EXCEPTION; | ||
} | ||
// 2 = SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the constant rather than the value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had an error that it couldn't find header and just left it in the comment.
I've reinstalled my Windows LLVM setup since then, the error may have gone away. Lots of bugs have gone away with Clang 20. I'm making sure now that it's there. That version was built when there was way less support, back when V8 added Clang as a build environment. That was before you could just add Clang from the Visual Studio menu.
altercation: MINGW64 ... no longer MINGW32 no longer duping the tmpfile handle. that was because of some other function and it's not needed. improved os_tmpfile names of variables for clarity. JSTMPFile stores a js_mallocz'd buffer instead. frees buffer. enumerated JSSTDFileKind kind;
fixed flag: SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE tested
thank you for the opportunity of getting this in here. changes made. enummbed JSTMPFileKind. (it's just JSTMPFile, I didn't change JSSTDFile. I don't know who's project that affects. But the bool should be 1 for a pipe in the old code. It should work. so the best solutions to the symlink dir issue online are to open the raw shortcut or use kernel level functions to read the harddrive node directly. And I'm not getting paid for any of this, so that's not free, my laptop's not insured. If you want to learn the file format of a shortcut in windows, I'm sure that will work until windows 12 comes along. |
I have to manually test this change unless we add a detect user or detect group function. Win32 has no lstat. Moved the comment and admin flag to the top for ease of use until someone comes up with a better solution.
quickjs-libc.c
Outdated
if (ss->f) fclose(ss->f); | ||
if (ss->filename != 0) remove(ss->filename); | ||
js_free_rt(rt, ss->filename); | ||
} else if (s->f && !is_stdio(s->f)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can just return here rather than having the check duplicated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mean return and take the else out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty much. Well, you may need some extra cleanup, or a goto end...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes I left it open for cleanup before.
Added 'return;' and took out 'else'. I just wasn't sure what you meant.
quickjs-libc.c
Outdated
JS_FreeValue(ctx, obj); | ||
return JS_EXCEPTION; | ||
} | ||
fn_template = "\\qXXXXXXX"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make this static?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
made static. I always assumed the compiler was smart enough to do that. So I researched it and I get it, someone might want their strings on their stack, so the default is not.
I have always seen it in the string table, not on the stack. Researching it, maybe my compilers were optimizing that way, and I just assumed it was static by default. Maybe I'm thinking of a const string.
quickjs-libc.c
Outdated
env_tmp = getenv("TEMP"); | ||
if (env_tmp) { | ||
fn_len = strlen(env_tmp); | ||
fn_buff = js_malloc(ctx, fn_len + 10); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't use 10, if that is the length of the template, use strlen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
used strlen, but with a lot of addition around it.
I hated to malloc 10. That's why this got so busy.
And I memcpy the 0.
quickjs-libc.c
Outdated
memcpy(fn_buff, env_tmp, fn_len); | ||
memcpy(fn_buff + fn_len, fn_template, 10); | ||
} else { | ||
fn_buff = js_mallocz(ctx, 10); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can share the allocation and copy code across both branches by checking if you have an env var or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's wrong anyway. Even if there's no %TEMP% I put "/" and that would default to c:. That defeats the whole point. There are no create permissions there. I should throw an exception if I don't have TEMP. Otherwise I should have added "\" manually.
Let me know if you disagree. My original logic was to create in CWD if someone's stripped the environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no way around two ifs that I could see.
I admit, may be clearer for someone else to read the way you're suggesting.
quickjs-libc.c
Outdated
}; | ||
//int fd = dup(mkf); | ||
s->f = fdopen( mk_fd, "a+"); | ||
if (s->f == 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check if (!s->f
} | ||
err = CreateSymbolicLinkA(linkpath, target, ( isdirflag | | ||
SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE ) ) ; | ||
if (!err) err = GetLastError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: please use similar style to what we use all across the codebase
tests/test_std.js
Outdated
/* symlink in windows 10+ requres admin or SeCreateSymbolicLinkPrivilege privilege found under: | ||
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\ | ||
set IS_WIN_ADMIN_TEST_FLAG to 1 and run as Administrator to test win32 os.symlink */ | ||
const IS_WIN_ADMIN_TEST_FLAG = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than do this, check the error code and if it's a permission error then don't fail the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed.
as per other comment, it's making less sense that windows has done this to the feature.
tests/test_std.js
Outdated
@@ -168,9 +172,12 @@ function test_os() | |||
[st, err] = os.stat(fpath); | |||
assert(err, 0); | |||
assert(st.mode & os.S_IFMT, os.S_IFREG); | |||
assert(st.mtime, fdate); | |||
|
|||
if (!isWin) // returns some negative value in windows 11. had to remove this on my build. (CAP) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please undo this unrelated change, our test suite does not reproduce the problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll fix it, but this took me an hour to solve. it might be something in windows 11:
Error: assertion failed: got |-1000|, expected |10000|
I finally was able to verify the bug:
fdate = 18000000;
err = os.utimes(fpath, fdate, fdate);
you see anything before that was 1969 according to my timezone, and windows 11 would not handle it. That's in Windows 11 on all 4 different builds I'm doing. So my question in response is: what versions of Windows do you verify against? This could be a timezone issue.
There is no error to this. MSDN claims _time will return -1 on error, but it seems like something internal is getting -1 and setting that into the internal structure. Later it's stat which sees -1 and converts it to milliseconds. The linux version calls a different function that doesn't modify the time on failure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can check the CI taml file, we check against a few windows versions, 11 is amongst them.
Even if there is a timezone issue, it's not related to this PR so it should be handled in a different one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks. I had a minute and figured it out. It just glitches out to set that time before 5am here in NY time. That's 18 million milliseconds. The script needs more than 10,000.
I put 86 million 400 thousand milliseconds, which is 24 hours, which gets any user through Dec 31 1969 to Jan 1.
tests/test_std.js
Outdated
@@ -183,6 +190,14 @@ function test_os() | |||
assert(buf, fname); | |||
|
|||
assert(os.remove(link_path) === 0); | |||
|
|||
} else if (IS_WIN_ADMIN_TEST_FLAG) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned above, handle the failure gracefully on Windows.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we start the test and skip the test? I'll do that, but would you rather remove it at this point?
I know I said I'd use the feature, but now I'm using hard links. I will be frank with you, lstat needs to be working for all of this and that's too large of a change for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine by me, we can handle one change at a time. Keep this PR to tmpfile alone then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just exit gracefully or remove the link. I suppose you need to test removing the link.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry you commented as I had the screen un-refreshed. It looked ugly to me when I commented but it's growing on me. Silence is golden. It's whatever you want.
If someone is editing the file to test it, they can put a console.log in to see it. I removed the comment, and I just hate for another windows user to learn this the hard way.
Coincidentally this isn't a problem with hard links. I'm doing hard links in my batch file when I download the git and move test262 and it doesn't complain. If os.exec is fixed, I would just use that. I'm pretty sure that symlink isn't a hard link, right? That kind of makes Microsoft's decision silly.
tests/test_std.js
Outdated
@@ -298,3 +313,4 @@ test_interval(); | |||
test_timeout(); | |||
test_timeout_order(); | |||
test_stdio_close(); | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Drop the extra line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes in as requested and tested.
I will download and make sure after I've had a break.
removed extra line. win32 symlink fails on 1314 because admin rights required. removed flag.
cleaned up js_os_tmpfile cleaned up finalizer
fixed indention level
requested changes made. I've updated the merged copy of these two changes and I work from that, for my stuff. And I'm about a step away from having the windows version running test262. I used your cmake but I did manage to get Mingw64 to run it. I've crashed the board! Maybe removing the symlink makes more sense for now. If I work on this any further, it's going to be my own cross compatible version of lstat done initially as a c header. |
tested in Win11 MSYS2 Mingw64, Clang64, WSL Debian, MSVC 2023, Clang in MSVC 2022
finished modifications so that test_std can pass audit in windows.
adds Win32 os_symlink
modifies std_tmpfile for MINGW
adds destructor to std_File for tmpfile deletion
this does not contain os.exec or inclusion of Win32 std_test.js for that. It didn't test windows before, and that can probably be moved from test_std (considering it's not std it's os anyway). my change is separated and that test script is separated in that change.
test_std no longer tries to create a symlink in windows because you need admin rights, but it works if you test it manually.
also there's a time bug returning negative number I didn't get into removed from test_std