Skip to content

Commit 391e679

Browse files
committed
Sync _emscripten_thread_exit() with musl's pthread_exit
1 parent 71d627a commit 391e679

1 file changed

Lines changed: 23 additions & 10 deletions

File tree

system/lib/pthread/pthread_create.c

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
static void dummy_0() {}
3434
weak_alias(dummy_0, __pthread_tsd_run_dtors);
35+
weak_alias(dummy_0, __do_orphaned_stdio_locks);
36+
weak_alias(dummy_0, __dl_thread_cleanup);
3537

3638
static void __run_cleanup_handlers() {
3739
pthread_t self = __pthread_self();
@@ -306,11 +308,21 @@ void _emscripten_thread_exit(void* result) {
306308
// Call into the musl function that runs destructors of all thread-specific data.
307309
__pthread_tsd_run_dtors();
308310

311+
// If this is the main runtime thread, don't proceed with
312+
// termination of the thread, but prepare for exit to call
313+
// atexit handlers.
314+
if (emscripten_is_main_runtime_thread()) {
315+
exit(0);
316+
}
317+
318+
// At this point we are committed to thread termination.
319+
320+
// The thread list lock must be AS-safe.
309321
__tl_lock();
310322

311-
/* Process robust list in userspace to handle non-pshared mutexes
312-
* and the detached thread case where the robust list head will
313-
* be invalid when the kernel would process it. */
323+
// Process robust list in userspace to handle non-pshared mutexes
324+
// and the detached thread case where the robust list head will
325+
// be invalid when the kernel would process it.
314326
__vm_lock();
315327
volatile void *volatile *rp;
316328
while ((rp=self->robust_list.head) && rp != &self->robust_list.head) {
@@ -327,19 +339,18 @@ void _emscripten_thread_exit(void* result) {
327339
}
328340
__vm_unlock();
329341

330-
if (!--libc.threads_minus_1) libc.need_locks = 0;
342+
__do_orphaned_stdio_locks();
343+
__dl_thread_cleanup();
331344

345+
// Last, unlink thread from the list. This change will not be visible
346+
// until the lock is released via __tl_unlock() below.
347+
if (!--libc.threads_minus_1) libc.need_locks = 0;
332348
self->next->prev = self->prev;
333349
self->prev->next = self->next;
334350
self->prev = self->next = self;
335351

336352
__tl_unlock();
337353

338-
if (emscripten_is_main_runtime_thread()) {
339-
exit(0);
340-
return;
341-
}
342-
343354
// Not hosting a pthread anymore in this worker set __pthread_self to NULL
344355
__set_thread_state(NULL, 0, 0, 1);
345356

@@ -357,8 +368,10 @@ void _emscripten_thread_exit(void* result) {
357368
// When dynamic linking is enabled we need to keep track of zombie threads
358369
_emscripten_thread_exit_joinable(self);
359370
#endif
371+
372+
// Wake any joiner.
360373
a_store(&self->detach_state, DT_EXITED);
361-
__wake(&self->detach_state, 1, 1); // Wake any joiner.
374+
__wake(&self->detach_state, 1, 1);
362375
}
363376
}
364377

0 commit comments

Comments
 (0)