When creating new threads, initially block all signals.  It's up to the
client code (in vg_libpthread.c) to set the appropriate signal mask when
its ready.  This prevents a bug where a thread gets sent a signal before
even running any of its initialization code, which can cause problems
(particularly if the signal handler directly or indirectly uses TLS).


git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2332 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/vg_libpthread.c b/coregrind/vg_libpthread.c
index c5d7cb0..b64c543 100644
--- a/coregrind/vg_libpthread.c
+++ b/coregrind/vg_libpthread.c
@@ -71,6 +71,7 @@
 #include <sys/poll.h>
 #include <stdio.h>
 #include <errno.h>
+#include <signal.h>
 
 #include <stdlib.h>
 
@@ -752,6 +753,7 @@
       unsigned long sysinfo;
       void*         (*root_fn) ( void* );
       void*         arg;
+      sigset_t	    sigmask;
    }
    NewThreadInfo;
 
@@ -817,9 +819,6 @@
       set_gs(ldt_info.entry_number * 8 + 3);
    }
 
-   /* Free up the arg block that pthread_create malloced. */
-   my_free(info);
-
    /* Minimally observe the attributes supplied. */
    if (attr__detachstate != PTHREAD_CREATE_DETACHED
        && attr__detachstate != PTHREAD_CREATE_JOINABLE)
@@ -830,6 +829,13 @@
    /* Initialise thread specific state */
    init_thread_specific_state();
 
+   /* Now that everything is set up, restore our signal mask (we're
+      ready to accept signals) */
+   sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
+
+   /* Free up the arg block that pthread_create malloced. */
+   my_free(info);
+
    /* The root function might not return.  But if it does we simply
       move along to thread_exit_wrapper.  All other ways out for the
       thread (cancellation, or calling pthread_exit) lead there
@@ -922,6 +928,8 @@
 
    info->root_fn = __start_routine;
    info->arg     = __arg;
+   sigprocmask(SIG_SETMASK, NULL, &info->sigmask);
+
    VALGRIND_MAGIC_SEQUENCE(tid_child, VG_INVALID_THREADID /* default */,
                            VG_USERREQ__APPLY_IN_NEW_THREAD,
                            &thread_wrapper, info, 0, 0);
@@ -929,6 +937,7 @@
 
    if (__thredd)
       *__thredd = tid_child;
+
    return 0; /* success */
 }
 
diff --git a/coregrind/vg_scheduler.c b/coregrind/vg_scheduler.c
index 0ec739c..9fc4ec1 100644
--- a/coregrind/vg_scheduler.c
+++ b/coregrind/vg_scheduler.c
@@ -1918,8 +1918,9 @@
       print_sched_event(tid, msg_buf);
    }
 
-   /* We inherit our parent's signal mask. */
-   VG_(threads)[tid].sig_mask = VG_(threads)[parent_tid].sig_mask;
+   /* Start the thread with all signals blocked; it's up to the client
+      code to set the right signal mask when it's ready. */
+   VG_(ksigfillset)(&VG_(threads)[tid].sig_mask);
 
    /* Now that the signal mask is set up, create a proxy LWP for this thread */
    VG_(proxy_create)(tid);