diff options
author | Andreas Schwab <schwab@suse.de> | 2001-11-26 12:59:16 +0000 |
---|---|---|
committer | Andreas Schwab <schwab@suse.de> | 2001-11-26 12:59:16 +0000 |
commit | a86e3e5891c72314c8c5d64b56f12474c72c0563 (patch) | |
tree | cd4aa8b6f708881428b0563b08bb102e1fdc1a4d /linuxthreads | |
parent | dd09c3dcc91e9be3c1c8fca4486c286083540322 (diff) | |
download | glibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.zip glibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.tar.gz glibc-a86e3e5891c72314c8c5d64b56f12474c72c0563.tar.bz2 |
(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')
-rw-r--r-- | linuxthreads/manager.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index 41f53f3..c880819 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; |