Skip to content

Commit 2d96b78

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 75c7981 commit 2d96b78

File tree

6 files changed

+55
-4
lines changed

6 files changed

+55
-4
lines changed

src/postamble.js

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

462458
#if expectToReceiveOnModule('onExit')

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
@@ -432,6 +432,9 @@ function exitRuntime() {
432432
#if EXIT_RUNTIME
433433
callRuntimeCallbacks(__ATEXIT__);
434434
<<< ATEXITS >>>
435+
#endif
436+
#if USE_PTHREADS
437+
PThread.terminateAllThreads();
435438
#endif
436439
runtimeExited = true;
437440
}

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
@@ -2323,6 +2323,12 @@ def test_pthread_equal(self):
23232323
def test_pthread_dispatch_after_exit(self):
23242324
self.do_run_in_out_file_test('pthread/test_pthread_dispatch_after_exit.c')
23252325

2326+
@node_pthreads
2327+
def test_pthread_atexit(self):
2328+
self.set_setting('EXIT_RUNTIME')
2329+
self.set_setting('PTHREAD_POOL_SIZE', 1)
2330+
self.do_run_in_out_file_test('pthread/test_pthread_atexit.c')
2331+
23262332
@node_pthreads
23272333
def test_pthread_nested_work_queue(self):
23282334
self.set_setting('EXIT_RUNTIME')

0 commit comments

Comments
 (0)