Skip to content

Commit d73b161

Browse files
committed
Run atexit handlers before terminating all threads
Although not defined by the POSIX standard, it seems that on most systems, atexit handlers are run before threads are terminated.
1 parent 79bbf41 commit d73b161

File tree

6 files changed

+55
-6
lines changed

6 files changed

+55
-6
lines changed

src/postamble.js

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -453,9 +453,6 @@ function exit(status, implicit) {
453453
}
454454
#endif // ASSERTIONS
455455
} else {
456-
#if USE_PTHREADS
457-
PThread.terminateAllThreads();
458-
#endif
459456
exitRuntime();
460457
}
461458

@@ -465,9 +462,6 @@ function exit(status, implicit) {
465462
function procExit(code) {
466463
EXITSTATUS = code;
467464
if (!keepRuntimeAlive()) {
468-
#if USE_PTHREADS
469-
PThread.terminateAllThreads();
470-
#endif
471465
#if expectToReceiveOnModule('onExit')
472466
if (Module['onExit']) Module['onExit'](code);
473467
#endif

src/postamble_minimal.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ function run() {
3030
callRuntimeCallbacks(__ATEXIT__);
3131
<<< ATEXITS >>>
3232
#endif
33+
#if USE_PTHREADS
34+
PThread.terminateAllThreads();
35+
#endif
3336

3437
#if IN_TEST_HARNESS
3538
// fflush() filesystem stdio for test harness, since there are existing

src/preamble.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,9 @@ function exitRuntime() {
434434
#if EXIT_RUNTIME
435435
callRuntimeCallbacks(__ATEXIT__);
436436
<<< ATEXITS >>>
437+
#endif
438+
#if USE_PTHREADS
439+
PThread.terminateAllThreads();
437440
#endif
438441
runtimeExited = true;
439442
}

tests/pthread/test_pthread_atexit.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include <assert.h>
2+
#include <pthread.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
6+
#include "emscripten.h"
7+
#include "emscripten/threading.h"
8+
9+
static _Atomic int threadCounter = 0;
10+
static _Atomic int running = 1;
11+
static pthread_t thread;
12+
13+
void *workerThread(void* arg) {
14+
threadCounter++;
15+
16+
while (running)
17+
emscripten_thread_sleep(1000);
18+
19+
threadCounter--;
20+
21+
return NULL;
22+
}
23+
24+
void terminateThread() {
25+
running = 0;
26+
27+
int res = 0;
28+
int rc = pthread_join(thread, (void**)&res);
29+
assert(rc == 0);
30+
assert(res == 0);
31+
32+
printf("done waiting - counter is: %d\n", threadCounter);
33+
}
34+
35+
int main(int argc, char* argv[]) {
36+
int rc = atexit(terminateThread);
37+
assert(rc == 0);
38+
39+
rc = pthread_create(&thread, NULL, workerThread, NULL);
40+
assert(rc == 0);
41+
return 0;
42+
}

tests/pthread/test_pthread_atexit.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
done waiting - counter is: 0

tests/test_core.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,12 @@ def test_pthread_abort(self):
23442344
self.add_pre_run("Module.onAbort = function() { console.log('onAbort called'); }")
23452345
self.do_run_in_out_file_test('pthread/test_pthread_abort.c', assert_returncode=NON_ZERO)
23462346

2347+
@node_pthreads
2348+
def test_pthread_atexit(self):
2349+
self.set_setting('EXIT_RUNTIME')
2350+
self.set_setting('PTHREAD_POOL_SIZE', 1)
2351+
self.do_run_in_out_file_test('pthread/test_pthread_atexit.c')
2352+
23472353
def test_tcgetattr(self):
23482354
self.do_runf(test_file('termios/test_tcgetattr.c'), 'success')
23492355

0 commit comments

Comments
 (0)