aboutsummaryrefslogtreecommitdiff
path: root/nptl
diff options
context:
space:
mode:
Diffstat (limited to 'nptl')
-rw-r--r--nptl/descr.h10
-rw-r--r--nptl/pthread_create.c46
2 files changed, 32 insertions, 24 deletions
diff --git a/nptl/descr.h b/nptl/descr.h
index 9dcf480bdf..e1c7db5473 100644
--- a/nptl/descr.h
+++ b/nptl/descr.h
@@ -332,9 +332,8 @@ struct pthread
/* True if thread must stop at startup time. */
bool stopped_start;
- /* The parent's cancel handling at the time of the pthread_create
- call. This might be needed to undo the effects of a cancellation. */
- int parent_cancelhandling;
+ /* Formerly used for dealing with cancellation. */
+ int parent_cancelhandling_unsed;
/* Lock to synchronize access to the descriptor. */
int lock;
@@ -391,6 +390,11 @@ struct pthread
/* Resolver state. */
struct __res_state res;
+ /* Signal mask for the new thread. Used during thread startup to
+ restore the signal mask. (Threads are launched with all signals
+ masked.) */
+ sigset_t sigmask;
+
/* Indicates whether is a C11 thread created by thrd_creat. */
bool c11;
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index 7c752d0f99..afd379e89a 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -369,7 +369,6 @@ __free_tcb (struct pthread *pd)
}
}
-
/* Local function to start thread and handle cleanup.
createthread.c defines the macro START_THREAD_DEFN to the
declaration that its create_thread function will refer to, and
@@ -385,10 +384,6 @@ START_THREAD_DEFN
/* Initialize pointers to locale data. */
__ctype_init ();
- /* Allow setxid from now onwards. */
- if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
- futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
-
#ifndef __ASSUME_SET_ROBUST_LIST
if (__set_robust_list_avail >= 0)
#endif
@@ -399,18 +394,6 @@ START_THREAD_DEFN
sizeof (struct robust_list_head));
}
- /* If the parent was running cancellation handlers while creating
- the thread the new thread inherited the signal mask. Reset the
- cancellation signal mask. */
- if (__glibc_unlikely (pd->parent_cancelhandling & CANCELING_BITMASK))
- {
- sigset_t mask;
- __sigemptyset (&mask);
- __sigaddset (&mask, SIGCANCEL);
- INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_UNBLOCK, &mask,
- NULL, _NSIG / 8);
- }
-
/* This is where the try/finally block should be created. For
compilers without that support we do use setjmp. */
struct pthread_unwind_buf unwind_buf;
@@ -432,6 +415,12 @@ START_THREAD_DEFN
unwind_buf.priv.data.prev = NULL;
unwind_buf.priv.data.cleanup = NULL;
+ __libc_signal_restore_set (&pd->sigmask);
+
+ /* Allow setxid from now onwards. */
+ if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
+ futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
+
if (__glibc_likely (! not_first_call))
{
/* Store the new cleanup handler info. */
@@ -722,10 +711,6 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
CHECK_THREAD_SYSINFO (pd);
#endif
- /* Inform start_thread (above) about cancellation state that might
- translate into inherited signal state. */
- pd->parent_cancelhandling = THREAD_GETMEM (THREAD_SELF, cancelhandling);
-
/* Determine scheduling parameters for the thread. */
if (__builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
&& (iattr->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)) != 0)
@@ -771,6 +756,21 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
ownership of PD (see CONCURRENCY NOTES above). */
bool stopped_start = false; bool thread_ran = false;
+ /* Block all signals, so that the new thread starts out with
+ signals disabled. This avoids race conditions in the thread
+ startup. */
+ sigset_t original_sigmask;
+ __libc_signal_block_all (&original_sigmask);
+
+ /* Conceptually, the new thread needs to inherit the signal mask of
+ this thread. Therefore, it needs to restore the saved signal
+ mask of this thread, so save it in the startup information. */
+ pd->sigmask = original_sigmask;
+
+ /* Reset the cancellation signal mask in case this thread is running
+ cancellation. */
+ __sigdelset (&pd->sigmask, SIGCANCEL);
+
/* Start the thread. */
if (__glibc_unlikely (report_thread_creation (pd)))
{
@@ -813,6 +813,10 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
retval = create_thread (pd, iattr, &stopped_start,
STACK_VARIABLES_ARGS, &thread_ran);
+ /* Return to the previous signal mask, after creating the new
+ thread. */
+ __libc_signal_restore_set (&original_sigmask);
+
if (__glibc_unlikely (retval != 0))
{
if (thread_ran)