[patch] workaround for GNU/Linux pthread_exit() bug
See below for a patch to dispatch_main() that is needed on GNU/Linux. This platform cannot call pthread_exit() from the main thread because of an undocumented bug that causes the process to become a zombie. As an alternative, this patch manually calls the TSD destructors, blocks all signals, and parks the main thread using pause(). If there is anything else that needs to be done to make this a viable alternative to calling pthread_exit(), please let me know. Regards, - Mark $ svn di src/queue.c Index: src/queue.c =================================================================== --- src/queue.c (revision 197) +++ src/queue.c (working copy) @@ -941,8 +941,32 @@ if (pthread_main_np()) { #endif _dispatch_program_is_probably_callback_driven = true; +#if defined(__linux__) + /* + * Workaround for a GNU/Linux bug that causes the process to + * become a zombie when the main thread calls pthread_exit(). + */ + sigset_t mask; + void *p; + + p = pthread_getspecific(dispatch_queue_key); + if (p != NULL) + _dispatch_queue_cleanup(p); + p = pthread_getspecific(dispatch_sema4_key); + if (p != NULL) + _dispatch_release(p); + p = pthread_getspecific(dispatch_cache_key); + if (p != NULL) + _dispatch_cache_cleanup2(p); + + sigfillset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, NULL); + pause(); + DISPATCH_CRASH("pause() returned"); +#else /* !defined(__linux__) */ pthread_exit(NULL); DISPATCH_CRASH("pthread_exit() returned"); +#endif #if HAVE_PTHREAD_MAIN_NP } DISPATCH_CLIENT_CRASH("dispatch_main() must be called on the main thread");
That's fairly interesting. I had to do this change a while ago as Windows does not know tls destructors at all. Oddly enough I experienced issues on some versions of Linux only. The latest incarnation of Open SuSe 64bit (11.4 I think) had issues, but only when executing C++ code before calling dispatch_main() whereas Ubuntu 10.10 made no problems at all. The change below fixed that behaviour as well. I consider your patch quite necessary as it - as a side effect - will increase the readability of the code. Someone taking a first glance at the code will have no way to understand how a call to pthread_exit() can cause a worker for the main queue to emerge. When seing the destructors getting called it is a lot easier. - Marius Am 16.05.2011 03:12, schrieb Mark Heily:
See below for a patch to dispatch_main() that is needed on GNU/Linux. This platform cannot call pthread_exit() from the main thread because of an undocumented bug that causes the process to become a zombie. As an alternative, this patch manually calls the TSD destructors, blocks all signals, and parks the main thread using pause().
If there is anything else that needs to be done to make this a viable alternative to calling pthread_exit(), please let me know.
Regards,
- Mark
$ svn di src/queue.c Index: src/queue.c =================================================================== --- src/queue.c (revision 197) +++ src/queue.c (working copy) @@ -941,8 +941,32 @@ if (pthread_main_np()) { #endif _dispatch_program_is_probably_callback_driven = true; +#if defined(__linux__) + /* + * Workaround for a GNU/Linux bug that causes the process to + * become a zombie when the main thread calls pthread_exit(). + */ + sigset_t mask; + void *p; + + p = pthread_getspecific(dispatch_queue_key); + if (p != NULL) + _dispatch_queue_cleanup(p); + p = pthread_getspecific(dispatch_sema4_key); + if (p != NULL) + _dispatch_release(p); + p = pthread_getspecific(dispatch_cache_key); + if (p != NULL) + _dispatch_cache_cleanup2(p); + + sigfillset(&mask); + pthread_sigmask(SIG_SETMASK, &mask, NULL); + pause(); + DISPATCH_CRASH("pause() returned"); +#else /* !defined(__linux__) */ pthread_exit(NULL); DISPATCH_CRASH("pthread_exit() returned"); +#endif #if HAVE_PTHREAD_MAIN_NP } DISPATCH_CLIENT_CRASH("dispatch_main() must be called on the main thread"); _______________________________________________ libdispatch-dev mailing list libdispatch-dev@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/libdispatch-dev
participants (2)
-
Marius Zwicker
-
Mark Heily