|
48 | 48 | #define pthread_workqueue_t void*
|
49 | 49 | #endif
|
50 | 50 |
|
| 51 | +static void _dispatch_sig_thread(void *ctxt); |
51 | 52 | static void _dispatch_cache_cleanup(void *value);
|
52 | 53 | static void _dispatch_sync_f(dispatch_queue_t dq, void *ctxt,
|
53 | 54 | dispatch_function_t func, pthread_priority_t pp);
|
@@ -5693,6 +5694,17 @@ dispatch_main(void)
|
5693 | 5694 | _dispatch_object_debug(&_dispatch_main_q, "%s", __func__);
|
5694 | 5695 | _dispatch_program_is_probably_callback_driven = true;
|
5695 | 5696 | _dispatch_ktrace0(ARIADNE_ENTER_DISPATCH_MAIN_CODE);
|
| 5697 | +#ifdef __linux__ |
| 5698 | + // On Linux, if the main thread calls pthread_exit, the process becomes a zombie. |
| 5699 | + // To avoid that, just before calling pthread_exit we register a TSD destructor |
| 5700 | + // that will call _dispatch_sig_thread -- thus capturing the main thread in sigsuspend. |
| 5701 | + // This relies on an implementation detail (currently true in glibc) that TSD destructors |
| 5702 | + // will be called in the order of creation to cause all the TSD cleanup functions to |
| 5703 | + // run before the thread becomes trapped in sigsuspend. |
| 5704 | + pthread_key_t dispatch_main_key; |
| 5705 | + pthread_key_create(&dispatch_main_key, _dispatch_sig_thread); |
| 5706 | + pthread_setspecific(dispatch_main_key, &dispatch_main_key); |
| 5707 | +#endif |
5696 | 5708 | pthread_exit(NULL);
|
5697 | 5709 | DISPATCH_INTERNAL_CRASH(errno, "pthread_exit() returned");
|
5698 | 5710 | #if HAVE_PTHREAD_MAIN_NP
|
@@ -5776,11 +5788,14 @@ _dispatch_queue_cleanup2(void)
|
5776 | 5788 | // overload the "probably" variable to mean that dispatch_main() or
|
5777 | 5789 | // similar non-POSIX API was called
|
5778 | 5790 | // this has to run before the DISPATCH_COCOA_COMPAT below
|
| 5791 | + // See dispatch_main for call to _dispatch_sig_thread on linux. |
| 5792 | +#ifndef __linux__ |
5779 | 5793 | if (_dispatch_program_is_probably_callback_driven) {
|
5780 | 5794 | _dispatch_barrier_async_detached_f(_dispatch_get_root_queue(
|
5781 | 5795 | _DISPATCH_QOS_CLASS_DEFAULT, true), NULL, _dispatch_sig_thread);
|
5782 | 5796 | sleep(1); // workaround 6778970
|
5783 | 5797 | }
|
| 5798 | +#endif |
5784 | 5799 |
|
5785 | 5800 | #if DISPATCH_COCOA_COMPAT
|
5786 | 5801 | dispatch_once_f(&_dispatch_main_q_port_pred, dq,
|
|
0 commit comments