emscripten-core / emscripten-core/emscripten
Defining setStatus with headless flag causes node process to silently exit...
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
**Version of emscripten/emsdk:**
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.47-git
clang version 16.0.6
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /nix/store/2sbmywkxfmjw5wbn53vxqckm0xm8yffs-emscripten-llvm-3.1.47/bin
**Issue Description:**
I'm working on a project with a complex make file, so sharing the exact command that's being run will be a bit difficult, as I'm not super familiar with `make`.
That being said, I have a fairly good understanding of what's happening, so let me try to break it down:
- I'm compiling with `-s HEADLESS=1` so that I can run an SDL project in node.js ([doom-wasm](https://github.com/cloudflare/doom-wasm) running as a dedicated server)
- I'm compiling with `-s MODULARIZE=1`, and running `const module = await createModule(...)` to construct the module
- Nothing after the await runs, and the process exists, despite having a sleep loop that should hold the process open
- if I remove `setStatus` from the options object passed to `createModule`, it works as expected
This was quite baffling to me, but eventually I realized that:
- if `setStatus` is defined, `doRun` is run inside of a `setTimeout`
- if `HEADLESS` is defined, `setTimeout` is replaced by a custom implementation
- this custom implementation doesn't actually cause anything to be placed on the node event loop
- thus, if you're awaiting the promise returned by `createModule`, then the event loop runs out of things to do, and the process silently exits.
You can see a minimal reproduce of this if you simulate the `readyPromiseResolve` bit manually:
```js
let resolve, reject;
const p = new Promise((res, rej) => { resolve = res; reject = rej; });
await p;
console.log("after p");
```
Even though there's a dangling promise being "awaited" on, there's not actually anything on the event loop that could cause the `resolve` to... resolve... so the process just exits.
This is *really* surprising, given the lack of documentation for `-s HEADLESS`, and the fact that it's only triggered if a seemingly unrelated methods, `setStatus`, is defined.
(I noticed some conversations like #20554 mention that this isn't well maintained, so it's also worth weighing in on HEADLESS being useful for non-testing use cases, so if there's a recommended alternative to running emscripten projects with an emulated browser environment, would also love that advice!)
Contributor guide
Assessment
This issue has not been assessed yet.