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