-
Notifications
You must be signed in to change notification settings - Fork 181
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
Changes from 13 commits
6ee553f
f323678
7774b71
ba9e4c4
3d43bdb
60c56b1
a5395d3
e7e1a1f
18baa91
11e0daa
e402f19
e91b646
330df2a
7b68bff
4c04f21
f29e7b5
8d8b524
ec31538
68ec872
8988eca
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1034,6 +1034,14 @@ typedef struct { | |
bool is_popen; | ||
} JSSTDFile; | ||
|
||
#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 commentThe reason will be displayed to describe this comment to others. Learn more. Use an enum to be more readable please. |
||
char filename[64]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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? |
||
} JSTMPFile; | ||
#endif | ||
|
||
static bool is_stdio(FILE *f) | ||
{ | ||
return f == stdin || f == stdout || f == stderr; | ||
|
@@ -1044,13 +1052,22 @@ static void js_std_file_finalizer(JSRuntime *rt, JSValueConst val) | |
JSThreadState *ts = js_get_thread_state(rt); | ||
JSSTDFile *s = JS_GetOpaque(val, ts->std_file_class_id); | ||
if (s) { | ||
#if defined(__MINGW32__) || defined(__MINGW64__) | ||
JSTMPFile *ss = (JSTMPFile*) s; | ||
if (ss->is_kind==2) { | ||
if (ss->f) fclose(ss->f); | ||
if (ss->filename[0] != 0) remove(ss->filename); | ||
} else if (s->f && !is_stdio(s->f)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. yes I left it open for cleanup before. |
||
#else | ||
if (s->f && !is_stdio(s->f)) { | ||
#endif | ||
#if !defined(__wasi__) | ||
if (s->is_popen) | ||
pclose(s->f); | ||
else | ||
#endif | ||
fclose(s->f); | ||
|
||
} | ||
js_free_rt(rt, s); | ||
} | ||
|
@@ -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 commentThe reason will be displayed to describe this comment to others. Learn more. Actually, why are we doing all of this when MinGW already has There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe 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! |
||
int argc, JSValueConst *argv) | ||
{ | ||
JSRuntime *rt = JS_GetRuntime(ctx); | ||
JSThreadState *ts = js_get_thread_state(rt); | ||
JSTMPFile *s; | ||
JSValue obj; | ||
obj = JS_NewObjectClass(ctx, ts->std_file_class_id); | ||
if (JS_IsException(obj)) | ||
return obj; | ||
s = js_mallocz(ctx, sizeof(*s)); | ||
if (!s) { | ||
JS_FreeValue(ctx, obj); | ||
return JS_EXCEPTION; | ||
} | ||
|
||
char * env = getenv("TMP"); | ||
if (!env) | ||
env = getenv("TEMP"); | ||
int i = 0; | ||
if (env) { | ||
while (env[i]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe 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. |
||
s->filename[i] = env[i]; | ||
i++; | ||
if (i > 50) | ||
return JS_NULL; | ||
} | ||
} | ||
char* fname = &s->filename[i]; | ||
char* templ = "\\qXXXXXXX"; | ||
while (templ[0]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. memcpy? |
||
fname[0] = templ[0]; | ||
fname++; templ++; | ||
} | ||
fname[0] = 0; | ||
int mkf = mkstemp(s->filename); | ||
if (mkf == -1) { | ||
JS_FreeValue(ctx, obj); | ||
js_free(ctx, s); | ||
return JS_NULL; | ||
} | ||
int fd = dup(mkf); | ||
s->f = fdopen( fd, "a+"); | ||
close(mkf); | ||
if (argc >= 1) | ||
js_set_error_object(ctx, argv[0], s->f ? 0 : errno); | ||
if (!s->f) { | ||
JS_FreeValue(ctx, obj); | ||
js_free(ctx, s); | ||
return JS_NULL; | ||
} | ||
s->is_kind = 2; | ||
JS_SetOpaque(obj, s); | ||
return obj; | ||
} | ||
#else // MINGW | ||
static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, | ||
int argc, JSValueConst *argv) | ||
{ | ||
|
@@ -1218,7 +1292,8 @@ static JSValue js_std_tmpfile(JSContext *ctx, JSValueConst this_val, | |
return JS_NULL; | ||
return js_new_std_file(ctx, f, false); | ||
} | ||
#endif | ||
#endif // !MINGW | ||
#endif // WASI | ||
|
||
static JSValue js_std_sprintf(JSContext *ctx, JSValueConst this_val, | ||
int argc, JSValueConst *argv) | ||
|
@@ -3055,9 +3130,8 @@ static JSValue js_os_realpath(JSContext *ctx, JSValueConst this_val, | |
} | ||
return make_string_error(ctx, buf, err); | ||
} | ||
#endif | ||
|
||
#if !defined(_WIN32) && !defined(__wasi__) | ||
/* in WIN32: (0 | err) os.symlink(target, linkpath, bool isDirectory) | ||
@ msdn: linkpath and target have reversed meaning than symlink! */ | ||
static JSValue js_os_symlink(JSContext *ctx, JSValueConst this_val, | ||
int argc, JSValueConst *argv) | ||
{ | ||
|
@@ -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 commentThe 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 commentThe 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: The line below it was supposed to be: err = CreateSymbolicLinkA(linkpath, target, ( isdirflag | 2 ) ) ; There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. You've left the change request. Is that for this? |
||
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 commentThe 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 commentThe 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. |
||
err = CreateSymbolicLinkA(linkpath, target, ( 2 ) ) ; | ||
if (!err) err = GetLastError(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
||
else err = 0; | ||
#else | ||
err = js_get_errno(symlink(target, linkpath)); | ||
#endif | ||
JS_FreeCString(ctx, target); | ||
JS_FreeCString(ctx, linkpath); | ||
return JS_NewInt32(ctx, err); | ||
} | ||
#endif | ||
|
||
#if !defined(_WIN32) && !defined(__wasi__) | ||
/* return [path, errorcode] */ | ||
static JSValue js_os_readlink(JSContext *ctx, JSValueConst this_val, | ||
int argc, JSValueConst *argv) | ||
|
@@ -4113,10 +4200,10 @@ static const JSCFunctionListEntry js_os_funcs[] = { | |
JS_CFUNC_DEF("sleep", 1, js_os_sleep ), | ||
#if !defined(__wasi__) | ||
JS_CFUNC_DEF("realpath", 1, js_os_realpath ), | ||
JS_CFUNC_DEF("symlink", 2, js_os_symlink ), | ||
#endif | ||
#if !defined(_WIN32) && !defined(__wasi__) | ||
JS_CFUNC_MAGIC_DEF("lstat", 1, js_os_stat, 1 ), | ||
JS_CFUNC_DEF("symlink", 2, js_os_symlink ), | ||
JS_CFUNC_DEF("readlink", 1, js_os_readlink ), | ||
JS_CFUNC_DEF("exec", 1, js_os_exec ), | ||
JS_CFUNC_DEF("getpid", 0, js_os_getpid ), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -168,9 +168,16 @@ 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 commentThe 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 commentThe 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:
I finally was able to verify the bug:
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 was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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. |
||
assert(st.mtime, fdate); | ||
|
||
/* symlink in windows 10+ requres admin or SeCreateSymbolicLinkPrivilege privilege found under: | ||
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\ | ||
*/ | ||
const IS_WIN_ADMIN_TEST_FLAG = 0; | ||
if (!isWin) { | ||
|
||
err = os.symlink(fname, link_path); | ||
assert(err, 0); | ||
|
||
|
@@ -183,6 +190,18 @@ 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 commentThe 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 commentThe 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? There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe 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. |
||
|
||
err = os.symlink(fname, link_path); | ||
assert(err, 0); | ||
|
||
[st, err] = os.lstat(link_path); | ||
assert(err, 0); | ||
assert(st.mode & os.S_IFMT, os.S_IFLNK); | ||
|
||
assert(os.remove(link_path) === 0); | ||
|
||
} | ||
|
||
[buf, err] = os.getcwd(); | ||
|
@@ -298,3 +317,5 @@ test_interval(); | |
test_timeout(); | ||
test_timeout_order(); | ||
test_stdio_close(); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. changes in as requested and tested. |
||
std.exit(0); | ||
coreyapowell marked this conversation as resolved.
Show resolved
Hide resolved
|
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.