mirror of
https://sourceware.org/git/glibc.git
synced 2025-12-24 17:51:17 +03:00
nptl: Perform signal initialization upon pthread_create
Install signal handlers and unblock signals before pthread_create creates the first thread. create_thread in sysdeps/unix/sysv/linux/createthread.c can send SIGCANCEL to the current thread, so the SIGCANCEL handler is currently needed even if pthread_cancel is never called. (The way timer_create uses SIGCANCEL does not need a signal handler; both SIG_DFL and SIG_IGN dispositions should work.) Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user