-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Fix EXPORT_ES6 + USE_PTHREADS #8306
Conversation
Import returns a promise, so things had to be rearranged. I think I could have used promise.resolve() instead, but that's something to revisit if I can actually get this working.
Currently "_emscripten_futex_wake" is being optimised away, so I need to compile with Edit: Seems to be fixed now. Not sure how that happened. |
Things seem to be mostly working now. I don't know why the test are failing, those webgl tests seem kind of flaky on firefox, so maybe it's unrelated. Edit: I'll probably also need to update shell_minimal.js at some point. |
…n the main thread. I feel like this should break things, but it seems to work properly with my tests.
@kripken or @sbc100, since you both commented on the original issue, could one of you take a look at this PR? I think I've got it working, I'm pretty sure the test failures are unrelated. I also want to add a test case for this, but I'm not really sure how to test something like this. I think I need some JS which loads the compiled ES6 module, but I don't rally know how to integrate this with the existing test framework. |
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.
@juj probably has more insight into all things pthreads.
emcc.py
Outdated
if shared.Settings.EXPORT_ES6: | ||
GETSCRIPT = "import.meta.url" | ||
else: | ||
GETSCRIPT = "typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined" |
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.
No need to make this local variable uppercase.
Would this be better names "script_url" or something like that?
Why is the js var called _scripteDir
? Isn't it the full URL?
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.
Yeah good point. I didn't name that, but it is a bit confusing. _scriptDir
can be a blob, or path to a script. Later on _scriptDir
is assigned to scriptDirectory
, which contains the directory of the script. I'm not sure what scriptDirectory
is used for.
Anyway import.meta.url
seems to return the same thing as document.currentScript.src
, the difference being that import.meta.url
works in a module, while document.currentScript.src
doesn't.
emscripten.py
Outdated
@@ -1666,6 +1666,10 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme | |||
|
|||
shared.Settings.MODULE_EXPORTS = module_exports = exported_implemented_functions + function_tables(function_table_data) | |||
|
|||
# Should only need to do this in the main thread. | |||
if shared.Settings.USE_PTHREADS: | |||
receiving = "if (!ENVIRONMENT_IS_PTHREAD) {\n" + receiving + "}\n" |
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.
But the stuff added to receiving below we do want on non-main-threads? Can you explain, perhaps write more in the comment 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.
In my testing it seems like these functions were already shared with the non-main-threads by the main thread. Calling these from a non-main-thread attempted to redefine them (as the same thing). No idea if that's how it's supposed to work.
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.
Based on where this line is, it just puts the runtime assertions stuff behind this check. What's special about them? As @sbc100 said, I think this should all be needed in pthreads too - do you have a test that fails without this change?
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.
When I tried to run the code before this change I was getting errors about the vars in this block being redefined. It seems like when initialising a thread these functions have already been defined (not sure how). Normally var redefinition isn't an issue as everything gets hoisted, so I assumed it was an ES6 module thing. I'll have to do some more testing, I can't remember exactly what error I was trying to avoid.
Although looking at that again I should add a check for if receiving
is an empty string.
Edit: The actual error I get is:
Uncaught (in promise) TypeError: Cannot assign to read only property '__ZSt18uncaught_exceptionv' of object '[object Object]'
__ZSt18uncaught_exceptionv just happens to be the first in the list, it seems to error on all of them, causing initialising pthreads to fail.
I had assumed that these were getting defined twice, once in the main thread, once in workers, but it looks like you can't just redefine things like that in an ES6 module. I don't know why. I'll change the settings check to if shared.Settings.USE_PTHREADS and shared.Settings.EXPORT_ES6 and receiving:
if I can't figure out how to get this 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.
That's a very odd error - I don't think we use read-only properties anywhere?
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, and sorry for my mistake earlier!
Ok, what I think is happening here is: when loaded as an ES6 module, the wasm exports object is an ES6 module export object, or behaves like one, and those are more "static" than normal JS objects. And we try to replace them with wrappers to add extra runtime error handling, and that fails.
But that doesn't explain why this is a problem only on workers but not on the main thread. It sounds like that could be a browser bug, in fact. That asm object is a wasm export object on both locations, so it should behave the same? Unless somehow only the worker is an ES6 context - I'm not too familiar with how those are created?
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.
Regardless, we can split this out from the rest of this PR, if it's separable.
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.
Yeah I don't really know too much about all that stuff either.
The change on that line allows EXPORT_ES6 + USE_PTHREADS to work with ASSERTIONS != 0. I think the best thing is to merge this PR as is, since by default ASSERTIONS=1.
Perhaps after this is merged another bug can be opened to fix those assertions?\
If you'd prefer I'm happy to remove that line, and just say that currently EXPORT_ES6 + USE_PTHREADS only work with ASSERTIONS=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.
Yeah, let's separate it out - a comment that says something like your last line there sounds good enough 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.
OK, I changed it to an assert, since the next line would just throw anyway. At least this way the developer gets a clear message about this not working. Once this is merged I'll open another issue to fix USE_PTHREADS + EXPORT_ES6 +ASSERTIONS.
Well the tests failed because the I'm happy for this to be merged, if everyone else is happy with the changes. |
emscripten.py
Outdated
@@ -1666,6 +1666,10 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme | |||
|
|||
shared.Settings.MODULE_EXPORTS = module_exports = exported_implemented_functions + function_tables(function_table_data) | |||
|
|||
# Should only need to do this in the main thread. | |||
if shared.Settings.USE_PTHREADS: | |||
receiving = "if (!ENVIRONMENT_IS_PTHREAD) {\n" + receiving + "}\n" |
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.
Based on where this line is, it just puts the runtime assertions stuff behind this check. What's special about them? As @sbc100 said, I think this should all be needed in pthreads too - do you have a test that fails without this change?
The |
… USE_PTHREADS is on (emscripten-core#8609)
…ke_context_current (emscripten-core#8613) And add a complete test for both that and for emscripten_webgl_create_context in that mode (which also tests emscripten-core#8579)
…en-core#8601) Also, add a mechanism for supporting renamed settings. This enables users in non-strict mode to use old name for the settings, but users in strict mode must use the modern name. Part of emscripten-core#8317
emscripten-core#8600) Specifying WASM_OBJECT_FILES=0 on the link line is current needed if one want to select LTO libraries. However this should not exclude some input being wasm object files. Fixes emscripten-core#8599
…pten-core#8618) * Update fetch API documentation because streaming is Firefox only * Added note about EMSCRIPTEN_FETCH_STREAM_DATA being Firefox only
This test now passed with the llvm backend.
Returning EINVAL error when trying to call fsync on fd representing UNIX pipe. This fixes http://posixtest.sourceforge.net/ fsync/7-1 test.
Previously these tests weren't actually checking the right thing. This should fix the logic to what I think the author was trying to do. Fixes emscripten-core#8620.
This works with the wasm backend, whether generating wasm or asm.js. Also added `emscripten_return_address` which implements the functionality of `__builtin_return_address` when running both wasm and asm.js.
Once detached threads are finished their execution they emit the 'exit' command. Instead of a noop they should rejoin the pool. Resolves emscripten-core#8201.
* Make sure to note temp files that we create there. We missed one. * Don't eagerly remove temp files there - they will be removed later anyhow. And we do need to keep alive the temp file that we return.
…emscripten-core#8643) We only use this in JS during startup (before compiled code is ready to run). Other usages should call malloc/sbrk directly for the full functionality. Fixes emscripten-core#8637
Well I merged everything from Incoming into my PR, but unfortunately I did a rebase instead of a regular merge. I'm not sure how to fix this without creating more mess (or if it even needs fixing?). |
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.
Looks good, thanks, just some minor comments.
It's fine to leave things rebased (+ any more commits), whatever's easier - we'll squash it all when we land it anyhow, so the details of the commits in the PR don't matter.
emscripten.py
Outdated
@@ -1699,6 +1699,10 @@ def create_receiving(function_table_data, function_tables_defs, exported_impleme | |||
|
|||
shared.Settings.MODULE_EXPORTS = module_exports = exported_implemented_functions + function_tables(function_table_data) | |||
|
|||
# Should only need to do this in the main thread. |
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 clarify this in the comment. I believe the issue is that when assertions are on, we emit code that is incompatible with ES6 currently? Can add a TODO in the comment to fix that.
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.
Good point, I missed the comment what I changed the behaviour.
@@ -35,6 +34,10 @@ var __performance_now_clock_drift = 0; | |||
// Cannot use console.log or console.error in a web worker, since that would risk a browser deadlock! https://bugzilla.mozilla.org/show_bug.cgi?id=1049091 | |||
// Therefore implement custom logging facility for threads running in a worker, which queue the messages to main thread to print. | |||
var Module = {}; | |||
#if EXPORT_ES6 |
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 we should also emit these lines if MODULARIZE as we do assign to them there as well (line 144/158), and for the same reason?
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.
The difference is that in normal (aka sloppy) JS you can define things without var/const/let. So defining PThread
like PThread = Module['PThread'];
is perfectly valid. However this is not valid inside an ES6 module as that enforces strict mode. That's why I had to declare them here.
I can change #if EXPORT_ES6
to #if MODULARIZE
if you want, but there may be a reason that it was initially done like that and I didn't want to break existing modularize code.
@@ -149,6 +163,7 @@ this.onmessage = function(e) { | |||
if (typeof FS !== 'undefined' && typeof FS.createStandardStreams === 'function') FS.createStandardStreams(); | |||
#endif | |||
postMessage({ cmd: 'loaded' }); | |||
#endif |
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 add a comment // MODULARIZE && EXPORT_ES6
so it's easier to match up the if and its end
Sounds good. I'll do the modularize changes as a separate commit later, which is probably better anyhow. I'm rerunning the chrome tests which all failed here - probably that's just bad luck, and the rerun will pass. I'll land this if so. |
I haven't managed to get this working, and I think I'm stuck, but I figured I'd create this PR so people can pick up where I left off. Or point out if I'm doing something wrong.