-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Proxy known handlers back to the main thread #17925
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
Changes from all commits
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -283,12 +283,8 @@ var LibraryPThread = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Worker wants to postMessage() to itself to implement setImmediate() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // emulation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| worker.postMessage(d); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if expectToReceiveOnModule('onAbort') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (cmd === 'onAbort') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Module['onAbort']) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Module['onAbort'](d['arg']); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (cmd === 'callHandler') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Module[d['handler']](...d['args']); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else if (cmd) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // The received message looks like something that should be handled by this message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // handler, (since there is a e.data.cmd field present), but is not one of the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -329,9 +325,33 @@ var LibraryPThread = { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert(wasmModule instanceof WebAssembly.Module, 'WebAssembly Module should have been loaded by now!'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // When running on a pthread, none of the incoming parameters on the module | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // object are present. Proxy known handlers back to the main thread if specified. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var handlers = []; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var knownHandlers = [ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if expectToReceiveOnModule('onExit') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'onExit', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if expectToReceiveOnModule('onAbort') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'onAbort', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if expectToReceiveOnModule('print') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'print', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #if expectToReceiveOnModule('printErr') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'printErr', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
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 print and printErr were previously not proxied? What happened when they were called from the thread previously?
Collaborator
Author
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. Indeed, these module handlers were previously not proxied causing the var out = Module['print'] || defaultPrint;
var err = Module['printErr'] || defaultPrintErr;Lines 428 to 429 in 30f50a9
For simple emscripten/src/library_syscall.js Lines 1087 to 1100 in 30f50a9
This issue occurred with WasmFS, as that implements emscripten/system/lib/wasmfs/special_files.cpp Lines 110 to 116 in 30f50a9
Lines 3364 to 3369 in 30f50a9
(+ it would be a performance penalty if these were always proxied to the main thread, as noticed in #17688 (comment))
Collaborator
Author
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. BTW, this bug only occurs when the handler is set outside the module. For example, it did not occur when emitting the handlers via
Collaborator
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. Can we avoid the needless proxying in the case when the handler is defined in the
Collaborator
Author
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'm not sure this can be done without too much hassle. For example, if someone does this in if (!Module.hasOwnProperty('print')) {
Module['print'] = function(x) {
console.log(x);
};
}
if (!Module.hasOwnProperty('printErr')) {
Module['printErr'] = function(x) {
console.error(x);
};
}(i.e. set the default It implies that |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (var handler of knownHandlers) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (Module.hasOwnProperty(handler)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handlers.push(handler); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Ask the new worker to load up the Emscripten-compiled page. This is a heavy operation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| worker.postMessage({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'cmd': 'load', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'handlers': handlers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If the application main .js file was loaded from a Blob, then it is not possible | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // to access the URL of the current script that could be passed to a Web Worker so that | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // it could load up the same file. In that case, developer must either deliver the Blob | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -139,6 +139,14 @@ self.onmessage = (e) => { | |||||||
| Module['dynamicLibraries'] = e.data.dynamicLibraries; | ||||||||
| #endif | ||||||||
|
|
||||||||
| // Use `const` here to ensure that the variable is scoped only to | ||||||||
| // that iteration, allowing safe reference from a closure. | ||||||||
| for (const handler of e.data.handlers) { | ||||||||
| Module[handler] = function() { | ||||||||
|
Collaborator
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. How about only setting this if
Collaborator
Author
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. Those handlers ( emscripten/src/library_pthread.js Lines 346 to 348 in 096a5de
So, in most cases, |
||||||||
| postMessage({ cmd: 'callHandler', handler, args: [...arguments] }); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| {{{ makeAsmImportsAccessInPthread('wasmMemory') }}} = e.data.wasmMemory; | ||||||||
|
|
||||||||
| #if LOAD_SOURCE_MAP | ||||||||
|
|
||||||||
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 if the handler is not present? (
expectToReceiveOnModulejust means that it could be present)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
Module[d['handler']]check is not necessary here since it's checked below withModule.hasOwnProperty(handler), and likewise for thoseexpectToReceiveOnModulechecks. Thus, this handler is called only if it's present inINCOMING_MODULE_JS_APIand if it's explicitly set on the module.