about summary refs log tree commit diff
path: root/linuxthreads/manager.c
diff options
context:
space:
mode:
authorAndreas Schwab <schwab@suse.de>2001-11-26 12:59:16 +0000
committerAndreas Schwab <schwab@suse.de>2001-11-26 12:59:16 +0000
commita86e3e5891c72314c8c5d64b56f12474c72c0563 (patch)
treecd4aa8b6f708881428b0563b08bb102e1fdc1a4d /linuxthreads/manager.c
parentdd09c3dcc91e9be3c1c8fca4486c286083540322 (diff)
downloadglibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.tar.gz
glibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.tar.xz
glibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.zip
(pthread_handle_create): Start the child thread with the cancel signal blocked, so that it does not handle it before the thread register is set up. Save errno from failed clone call.
Diffstat (limited to 'linuxthreads/manager.c')
-rw-r--r--linuxthreads/manager.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c
index 41f53f38ef..c8808197c1 100644
--- a/linuxthreads/manager.c
+++ b/linuxthreads/manager.c
@@ -526,6 +526,8 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
   char *guardaddr = NULL;
   size_t guardsize = 0;
   int pagesize = __getpagesize();
+  int saved_errno;
+  sigset_t newmask, oldmask;
 
   /* First check whether we have to change the policy and if yes, whether
      we can  do this.  Normally this should be done by examining the
@@ -611,6 +613,11 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
       if ((mask & (__pthread_threads_events.event_bits[idx]
 		   | event_maskp->event_bits[idx])) != 0)
 	{
+	  /* Block cancel signal in the child until it is fully
+	     initialized.  */
+	  sigemptyset(&newmask);
+	  sigaddset(&newmask, __pthread_sig_cancel);
+	  sigprocmask(SIG_BLOCK, &newmask, &oldmask);
 	  /* Lock the mutex the child will use now so that it will stop.  */
 	  __pthread_lock(new_thread->p_lock, NULL);
 
@@ -638,6 +645,8 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
 			CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 			__pthread_sig_cancel, new_thread);
 #endif
+	  saved_errno = errno;
+	  sigprocmask(SIG_SETMASK, &oldmask, NULL);
 	  if (pid != -1)
 	    {
 	      /* Now fill in the information about the new thread in
@@ -663,6 +672,11 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
     }
   if (pid == 0)
     {
+      /* Block cancel signal in the child until it is fully
+	 initialized.  */
+      sigemptyset(&newmask);
+      sigaddset(&newmask, __pthread_sig_cancel);
+      sigprocmask(SIG_BLOCK, &newmask, &oldmask);
 #ifdef NEED_SEPARATE_REGISTER_STACK
       pid = __clone2(pthread_start_thread,
 		     (void **)new_thread_bottom,
@@ -678,6 +692,8 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
 		    CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND |
 		    __pthread_sig_cancel, new_thread);
 #endif /* !NEED_SEPARATE_REGISTER_STACK */
+      saved_errno = errno;
+      sigprocmask(SIG_SETMASK, &oldmask, NULL);
     }
   /* Check if cloning succeeded */
   if (pid == -1) {
@@ -700,7 +716,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr,
     __pthread_handles[sseg].h_descr = NULL;
     __pthread_handles[sseg].h_bottom = NULL;
     __pthread_handles_num--;
-    return errno;
+    return saved_errno;
   }
   /* Insert new thread in doubly linked list of active threads */
   new_thread->p_prevlive = __pthread_main_thread;