emscripten-core / emscripten-core/emscripten
assertion failure when calling `terminateAllThreads` as a thread is finishing
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
This is with emcc version
```
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.0.2-git
clang version 14.0.0 (https://github.com/llvm/llvm-project.git 1a929525e86a20d0b3455a400d0dbed40b325a13)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /usr/local/opt/emscripten/libexec/llvm/bin
```
Here's some code:
```cpp
// lib.cc
#include
#include
#include
int do_work() {
return 42;
}
extern "C" void async_do_work() {
std::thread t([&] {
int result = do_work();
MAIN_THREAD_ASYNC_EM_ASM({
resolve($0);
}, result);
});
t.detach();
}
```
and a wrapper, injected with `--pre-js`:
```js
// wrapper.js
let resolve;
Module.do_work = () => {
let promise = new Promise(res => { resolve = res; });
Module._async_do_work();
return promise;
};
```
Compiled with
```
emcc -std=c++17 lib.cc -s USE_PTHREADS=1 -s EXPORTED_FUNCTIONS=_async_do_work -s DEMANGLE_SUPPORT=1 -s MODULARIZE=1 -s EXPORT_NAME=Init --pre-js wrapper.js -o lib.js
```
and run with
```js
// main.js
'use strict';
let init = typeof require === 'function' ? require('./lib.js') : Init;
(async () => {
let mod = await init();
console.log(await mod.do_work());
// await new Promise(res => setTimeout(res, 0));
console.log('cleaning up...');
mod.PThread.terminateAllThreads();
})().catch(e => {
console.log('caught');
console.error(e);
process.exit(1);
});
```
this produces
```
42
cleaning up...
Aborted(Assertion failed)
/Users/kevin/Code/emscripten-call-on-thread-bug/lib.js:235
throw ex;
^
RuntimeError: Aborted(Assertion failed)
at abort (/Users/kevin/Code/emscripten-call-on-thread-bug/lib.js:1745:11)
at assert (/Users/kevin/Code/emscripten-call-on-thread-bug/lib.js:874:5)
at Worker.worker.onmessage (/Users/kevin/Code/emscripten-call-on-thread-bug/lib.js:2233:13)
at Worker. (/Users/kevin/Code/emscripten-call-on-thread-bug/lib.js:2256:20)
at Worker.emit (node:events:390:28)
at MessagePort. (node:internal/worker:232:53)
at MessagePort.[nodejs.internal.kHybridDispatch] (node:internal/event_target:562:20)
at MessagePort.exports.emitMessage (node:internal/per_context/messageport:23:28)
```
The relevant lines in `lib.js` are
```js
} else if (cmd === 'detachedExit') {
assert(worker.pthread);
PThread.returnWorkerToPool(worker);
}
```
If you un-comment the `await new Promise` line in `main.js` it will work - it looks like the problem is specifically calling `terminateAllThreads` while a thread is in the process of shutting down already. Fortunately waiting until the next turn of the event loop is a straightforward workaround, so it's probably not a big deal.
https://github.com/emscripten-core/emscripten/issues/9486 had a similar exception, but it's not the same one.
Contributor guide
Assessment
This issue has not been assessed yet.