[libdispatch-dev] [patch] workaround for GNU/Linux pthread_exit() bug

Marius Zwicker marius at mlba-team.de
Tue May 17 11:12:40 PDT 2011


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 at lists.macosforge.org
> http://lists.macosforge.org/mailman/listinfo.cgi/libdispatch-dev



More information about the libdispatch-dev mailing list