diff options
Diffstat (limited to 'nptl/pthread_create.c')
-rw-r--r-- | nptl/pthread_create.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c index 7706564..772b5ef 100644 --- a/nptl/pthread_create.c +++ b/nptl/pthread_create.c @@ -56,6 +56,43 @@ static struct rtld_global *__nptl_rtld_global __attribute_used__ = &_rtld_global; #endif +/* This performs the initialization necessary when going from + single-threaded to multi-threaded mode for the first time. */ +static void +late_init (void) +{ + struct sigaction sa; + __sigemptyset (&sa.sa_mask); + + /* Install the cancellation signal handler (in static builds only if + pthread_cancel has been linked in). If for some reason we cannot + install the handler we do not abort. Maybe we should, but it is + only asynchronous cancellation which is affected. */ +#ifndef SHARED + extern __typeof (__nptl_sigcancel_handler) __nptl_sigcancel_handler + __attribute__ ((weak)); + if (__nptl_sigcancel_handler != NULL) +#endif + { + sa.sa_sigaction = __nptl_sigcancel_handler; + sa.sa_flags = SA_SIGINFO; + (void) __libc_sigaction (SIGCANCEL, &sa, NULL); + } + + /* Install the handle to change the threads' uid/gid. */ + sa.sa_sigaction = __nptl_setxid_sighandler; + sa.sa_flags = SA_SIGINFO | SA_RESTART; + (void) __libc_sigaction (SIGSETXID, &sa, NULL); + + /* The parent process might have left the signals blocked. Just in + case, unblock it. We reuse the signal mask in the sigaction + structure. It is already cleared. */ + __sigaddset (&sa.sa_mask, SIGCANCEL); + __sigaddset (&sa.sa_mask, SIGSETXID); + INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &sa.sa_mask, + NULL, __NSIG_BYTES); +} + /* Code to allocate and deallocate a stack. */ #include "allocatestack.c" @@ -459,9 +496,13 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr, { STACK_VARIABLES; - /* Avoid a data race in the multi-threaded case. */ + /* Avoid a data race in the multi-threaded case, and call the + deferred initialization only once. */ if (__libc_single_threaded) - __libc_single_threaded = 0; + { + late_init (); + __libc_single_threaded = 0; + } const struct pthread_attr *iattr = (struct pthread_attr *) attr; union pthread_attr_transparent default_attr; |