diff --git a/src/lib/libcore.js b/src/lib/libcore.js index 46fffb1192829..9143ee827a883 100644 --- a/src/lib/libcore.js +++ b/src/lib/libcore.js @@ -2094,8 +2094,13 @@ addToLibrary({ #endif try { #if PTHREADS - if (ENVIRONMENT_IS_PTHREAD) __emscripten_thread_exit(EXITSTATUS); - else + if (ENVIRONMENT_IS_PTHREAD) { + // exit the current thread, but only if there is one active. + // TODO(https://github.com/emscripten-core/emscripten/issues/25076): + // Unify this check with the runtimeExited check above + if (_pthread_self()) __emscripten_thread_exit(EXITSTATUS); + return; + } #endif _exit(EXITSTATUS); } catch (e) { @@ -2113,8 +2118,19 @@ addToLibrary({ }, #else // MINIMAL_RUNTIME - // MINIMAL_RUNTIME doesn't support the runtimeKeepalive stuff - $callUserCallback: (func) => func(), + $callUserCallback: (func) => { + // MINIMAL_RUNTIME doesn't support the runtimeKeepalive stuff, but under + // some circumstances it supportes `runtimeExited` +#if EXIT_RUNTIME + if (runtimeExited) { +#if ASSERTIONS + err('user callback triggered after runtime exited or application aborted. Ignoring.'); +#endif + return; + } +#endif + func(); + }, #endif // MINIMAL_RUNTIME $asmjsMangle: (x) => { diff --git a/src/lib/libpthread.js b/src/lib/libpthread.js index e251f4508ba23..9072ca392ff06 100644 --- a/src/lib/libpthread.js +++ b/src/lib/libpthread.js @@ -1094,18 +1094,16 @@ var LibraryPThread = { checkStackCookie(); #endif function finish(result) { -#if MINIMAL_RUNTIME +#if !MINIMAL_RUNTIME // In MINIMAL_RUNTIME the noExitRuntime concept does not apply to // pthreads. To exit a pthread with live runtime, use the function // emscripten_unwind_to_js_event_loop() in the pthread body. - __emscripten_thread_exit(result); -#else if (keepRuntimeAlive()) { EXITSTATUS = result; - } else { - __emscripten_thread_exit(result); + return; } #endif + __emscripten_thread_exit(result); } #if ASYNCIFY == 2 result = await result; @@ -1215,9 +1213,14 @@ var LibraryPThread = { 'pthread_self', '_emscripten_check_mailbox', '_emscripten_thread_mailbox_await'], - $checkMailbox: () => { + $checkMailbox: () => callUserCallback(() => { // Only check the mailbox if we have a live pthread runtime. We implement // pthread_self to return 0 if there is no live runtime. + // + // TODO(https://github.com/emscripten-core/emscripten/issues/25076): + // Is this check still needed? `callUserCallback` is supposed to + // ensure the runtime is alive, and if `_pthread_self` is NULL then the + // runtime certainly is *not* alive, so this should be a redundant check. var pthread_ptr = _pthread_self(); if (pthread_ptr) { // If we are using Atomics.waitAsync as our notification mechanism, wait @@ -1225,9 +1228,9 @@ var LibraryPThread = { // work that could otherwise arrive after we've finished processing the // mailbox and before we're ready for the next notification. __emscripten_thread_mailbox_await(pthread_ptr); - callUserCallback(__emscripten_check_mailbox); + __emscripten_check_mailbox(); } - }, + }), _emscripten_thread_mailbox_await__deps: ['$checkMailbox'], _emscripten_thread_mailbox_await: (pthread_ptr) => { diff --git a/test/code_size/test_codesize_minimal_pthreads.json b/test/code_size/test_codesize_minimal_pthreads.json index d2d287006e49b..65363c9767a11 100644 --- a/test/code_size/test_codesize_minimal_pthreads.json +++ b/test/code_size/test_codesize_minimal_pthreads.json @@ -1,10 +1,10 @@ { - "a.out.js": 7649, - "a.out.js.gz": 3768, + "a.out.js": 7660, + "a.out.js.gz": 3776, "a.out.nodebug.wasm": 19588, "a.out.nodebug.wasm.gz": 9025, - "total": 27237, - "total_gz": 12793, + "total": 27248, + "total_gz": 12801, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/test/code_size/test_codesize_minimal_pthreads_memgrowth.json b/test/code_size/test_codesize_minimal_pthreads_memgrowth.json index 3f98de951b241..cbae98d55659e 100644 --- a/test/code_size/test_codesize_minimal_pthreads_memgrowth.json +++ b/test/code_size/test_codesize_minimal_pthreads_memgrowth.json @@ -1,10 +1,10 @@ { - "a.out.js": 8076, - "a.out.js.gz": 3974, + "a.out.js": 8087, + "a.out.js.gz": 3978, "a.out.nodebug.wasm": 19589, "a.out.nodebug.wasm.gz": 9025, - "total": 27665, - "total_gz": 12999, + "total": 27676, + "total_gz": 13003, "sent": [ "a (memory)", "b (emscripten_get_now)", diff --git a/tools/emscripten.py b/tools/emscripten.py index 112e7eeb77d06..7dd9853f2e041 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -897,9 +897,7 @@ def install_debug_wrapper(sym): return False # Likewise `__trap` can occur before the runtime is initialized since it is used in # abort. - # pthread_self is currently called in some cases after the runtime has exited. - # TODO: Look into removing these, and improving our robustness around thread termination. - return sym not in {'__trap', 'pthread_self'} + return sym != '__trap' def should_export(sym):