BUILD_AS_WORKER: onmessage is installed too late under MODULARIZE, and is installed even on the main thread
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 55/100
- Tipo di issue
- Bug
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- javascript, wasm
- Ambito
- build-system, compilers
Direzione di ricerca
Inizia in src/build_as_worker.js e traccia come viene emesso e invocato il relativo IIFE con MODULARIZE, incluso il bootstrap del worker o il percorso --pre-js descritto nell'issue. Verifica il comportamento nel thread principale e per i messaggi inviati prima dell'esecuzione della factory. Il lavoro è completato quando le pagine non-worker mantengono il proprio gestore onmessage e i messaggi inviati prima della factory vengono conservati e consegnati dopo l'inizializzazione.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
src/build_as_worker.js wraps everything in an IIFE that installs the worker's onmessage:
(() => {
var messageBuffer = null, buffer = 0;
function flushMessages() { ... }
function messageResender() { ... }
onmessage = (msg) => {
// if main has not yet been called (mem init file, other async things), buffer messages
if (!runtimeInitialized) {
if (!messageBuffer) {
messageBuffer = [];
setTimeout(messageResender, 100);
}
messageBuffer.push(msg);
return;
}
...
}
})();
Two problems follow from when and where that IIFE runs. They are independent, so I have described both here and am happy to split them.
1. The handler is installed even when the module is not running in a worker
The IIFE runs in whatever environment loads the module, and assigns onmessage unconditionally. A module linked with -sBUILD_AS_WORKER that also runs on the main thread therefore overwrites window.onmessage, taking over message delivery for the whole page.
That is not a quiet takeover. Any message the page receives from another source now reaches this handler, which either aborts:
var func = Module['_' + msg.data['funcName']];
if (!func) abort('invalid worker function to call: ' + msg.data['funcName']);
or throws a TypeError outright, if msg.data is not an object with a funcName (a plain postMessage('...') from an embedding page or another library, for instance).
A guard at the top of the IIFE seems like the right fix:
if (!ENVIRONMENT_IS_WORKER) return;
2. Under MODULARIZE, messages that arrive before the factory runs are dropped
With -sMODULARIZE the IIFE lives inside the module factory, which the application invokes whenever it is ready. A worker, however, starts receiving messages the moment it is created — so there is a window between "worker script began executing" and "factory was called" during which these messages arrive.
The existing buffering does not cover that window. messageBuffer only starts collecting from inside the handler this IIFE installs, so it protects the interval between the factory running and runtimeInitialized — not the earlier one.
The natural workaround is to install a small buffering onmessage in the worker bootstrap (or via --pre-js) that collects messages until the factory is called. That does not work either: this IIFE overwrites onmessage and starts from messageBuffer = null, so everything the earlier handler collected is discarded.
The net effect is that a MODULARIZE'd BUILD_AS_WORKER module silently loses any message sent before the application gets around to instantiating it — with no way for the application to bridge the gap.
What we ship locally is for the IIFE to adopt a pre-existing buffer if one is present:
var messageBuffer = typeof workerMessageBuffer != 'undefined' ? workerMessageBuffer : null, buffer = 0;
// Upstream only starts the resender from inside its own handler, so an adopted
// buffer would otherwise never be flushed.
if (messageBuffer) setTimeout(messageResender, 100);
The bootstrap then just pushes into workerMessageBuffer until the factory is instantiated, and the module drains it. This has been running in production for us for a while.
I am raising this as an issue rather than sending the patch straight away, because the second half proposes a convention (workerMessageBuffer) that emscripten does not currently define, and you may well prefer a different shape — an explicit Module option, or having build_as_worker.js emit its own pre-factory bootstrap. Happy to send a PR for whichever you would like, and #1 can go on its own regardless.
Related, in that they are all variations of "the generated worker's onmessage is not reachable by the application": #20192, #11962, #8854.
Version
emscripten 6.0.3; the same code is on main as of today.
- Lingua principale
- C++
- Stelle
- 27.8k
- Fork
- 3.6k
- Merge medio
- 1g 3h
- PR unite (30g)
- 179
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di emscripten-core/emscripten
-
`other.test_cmake_cxx_import_std` fails on CMake 3.30–4.0.2 due to missing `CMAKE_EXPERIMENTAL_CXX_IMPORT_STD` UUIDsForse già presa @subhaushsingh l’ha presa 1 giorno fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
emscripten-core/emscripten#28160 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
emscripten-core/emscripten#27994 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
LEGACY_GL_EMULATION: generated fixed-function fragment shaders use mediump — fp16 overflow where mediump is half precisionForse già presa @TheTomBritton l’ha presa 12 giorni fa. ApertaDesktop OpenGL emulation
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
emscripten-core/emscripten#27948 · 4 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
emscripten-core/emscripten#27906 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
run_python, run_python_compiler could readlink -fForse già presa @kapouer l’ha presa 128 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 74/100
emscripten-core/emscripten#27211 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di emscripten-core/emscripten
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 65/100
-
[XLA] hlo/pass/README.md says passes implement Run; since the NVI change they implement RunImplAperta
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 91/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
NVIDIA-RTX/NRI#312 ·
I maintainer di solito rispondono entro 1 giorno
-
permute_q_b_proj / permute_wv_proj accept scale factors from another deviceForse già presa @0z5a l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
deepseek-ai/FlashMLA#247 ·
I maintainer di solito rispondono entro 1 giorno
-
Linux npm packaging leaves workspace files that block subsequent CI checkoutForse già presa @Spockkk0225 l’ha presa oggi. Apertaci
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
alibaba/neug#1195 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno