Skip to content

Commit 3208542

Browse files
committed
Linux: avoid zombie process when dispatch_main is called
If the main thread calls pthread_exit on Linux, the process becomes a zombie. Modify dispatch_main to avoid this by manually performing thread cleanup and pausing the thread instead of calling pthread_exit. This is an updated version of an old patch for this issue (https://lists.macosforge.org/pipermail/libdispatch-dev/2011-May/000522.html).
1 parent 92689ed commit 3208542

File tree

1 file changed

+41
-0
lines changed

1 file changed

+41
-0
lines changed

src/queue.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5693,8 +5693,49 @@ dispatch_main(void)
56935693
_dispatch_object_debug(&_dispatch_main_q, "%s", __func__);
56945694
_dispatch_program_is_probably_callback_driven = true;
56955695
_dispatch_ktrace0(ARIADNE_ENTER_DISPATCH_MAIN_CODE);
5696+
#ifdef __linux__
5697+
// On Linux, if the main thread calls pthread_exit the process becomes a zombie.
5698+
// Avoid zombification by manually doing the pthread cleanup
5699+
// and then pausing after masking all signals.
5700+
sigset_t mask;
5701+
void *p;
5702+
#if DISPATCH_USE_THREAD_LOCAL_STORAGE
5703+
p = pthread_getspecific(__dispatch_tsd_key);
5704+
if (p != NULL)
5705+
_libdispatch_tsd_cleanup(p);
5706+
#else
5707+
p = pthread_getspecific(dispatch_queue_key);
5708+
if (p != NULL)
5709+
_dispatch_queue_cleanup(p);
5710+
p = pthread_getspecific(dispatch_deferred_items_key);
5711+
if (p != NULL)
5712+
_dispatch_deferred_items_cleanup(p);
5713+
p = pthread_getspecific(dispatch_frame_key);
5714+
if (p != NULL)
5715+
_dispatch_frame_cleanup(p);
5716+
p = pthread_getspecific(dispatch_voucher_key);
5717+
if (p != NULL)
5718+
_voucher_thread_cleanup(p);
5719+
p = pthread_getspecific(dispatch_cache_key);
5720+
if (p != NULL)
5721+
_dispatch_cache_cleanup(p);
5722+
p = pthread_getspecific(dispatch_context_key);
5723+
if (p != NULL)
5724+
_dispatch_context_cleanup(p);
5725+
#if DISPATCH_LOCK_USE_SEMAPHORE_FALLBACK
5726+
p = pthread_getspecific(dispatch_sema4_key);
5727+
if (p != NULL)
5728+
_dispatch_thread_semaphore_dispose(p);
5729+
#endif
5730+
#endif
5731+
sigfillset(&mask);
5732+
pthread_sigmask(SIG_SETMASK, &mask, NULL);
5733+
pause();
5734+
DISPATCH_INTERNAL_CRASH(errno, "pause() returned");
5735+
#else
56965736
pthread_exit(NULL);
56975737
DISPATCH_INTERNAL_CRASH(errno, "pthread_exit() returned");
5738+
#endif
56985739
#if HAVE_PTHREAD_MAIN_NP
56995740
}
57005741
DISPATCH_CLIENT_CRASH(0, "dispatch_main() must be called on the main thread");

0 commit comments

Comments
 (0)