emscripten-core / emscripten-core/emscripten

assertion failure when calling `terminateAllThreads` as a thread is finishing

Open
#15,900 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.