emscripten-core / emscripten-core/emscripten
atexit()/EXIT_RUNTIME and pthreads
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
There are several current issues with the interaction of various pthreads features and runtime exit (i.e. executing functions registered with `atexit()` and/or `Module.onExit()`).
First, what *should* happen?
* In general, calling `exit()` from any thread should cause all atexit-registered destructors to run once. Its [man page](http://man7.org/linux/man-pages/man3/exit.3.html) says that it's not thread safe because it uses a global variable; but presumably if the program can guarantee it only gets called once, then the destructors should run on the calling thread.
* The man page for [pthread_exit](http://man7.org/linux/man-pages/man3/pthread_exit.3.html) says that calling it runs the destructors only after the last thread exits (presumably on the last thread left). [pthread_create](http://man7.org/linux/man-pages/man3/pthread_create.3.html) says that returning from a thread entry point is equivalent to calling `pthread_exit`.
* I haven't found a spec that says exactly what's supposed to when `main()` returns in the presence of threads, but the behavior on Linux seems to be that returning from `main()` is equivalent to calling `exit()` and runs the destructors.
In emscripten currently:
* When pthreads are enabled but no threads are ever created, (or if pthreads are created but never joined), destructors work :heavy_check_mark:
* However when a thread is created and subsequently joined (using PTHREAD_POOL to keep everything synchronous), the destructor runs, but then later `._emscripten_main_thread_process_queued_calls` runs and asserts that the runtime has not been exited. :x: (actually this failure happens even if no destructor is ever registered).
* Destructor calling fails anytime the destructors should be run off the main thread:
* PROXY_TO_PTHREAD=1 when registered and run from the thread that runs `main()` (even when no threads are created); result is a function signature mismatch with a callstack rooted at `worker.onmessage` :x:
* when registered from a `pthread_create()`ed thread; result is a function signature mismatch with a callstack from the implicit `exit()` inside `callMain()` :x:
Contributor guide
Assessment
This issue has not been assessed yet.