emscripten-core / emscripten-core/emscripten

atexit()/EXIT_RUNTIME and pthreads

Open
#9,251 4 comments 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

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

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.