diff options
-rw-r--r-- | lib/libthr/thread/thr_create.c | 17 | ||||
-rw-r--r-- | lib/libthr/thread/thr_private.h | 6 | ||||
-rw-r--r-- | lib/libthr/thread/thr_sig.c | 2 |
3 files changed, 24 insertions, 1 deletions
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index 03f0584..3bfd3b3 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -123,6 +123,11 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, if (new_thread->attr.flags & PTHREAD_CREATE_DETACHED) new_thread->tlflags |= TLFLAGS_DETACHED; + if (curthread->in_sigcancel_handler) + new_thread->unblock_sigcancel = 1; + else + new_thread->unblock_sigcancel = 0; + /* Add the new thread. */ new_thread->refcount = 1; _thr_link(curthread, new_thread); @@ -172,8 +177,10 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, ret = EAGAIN; } - if (create_suspended) + if (create_suspended) { __sys_sigprocmask(SIG_SETMASK, &oset, NULL); + SIGDELSET(oset, SIGCANCEL); + } if (ret != 0) { if (!locked) @@ -217,6 +224,14 @@ create_stack(struct pthread_attr *pattr) static void thread_start(struct pthread *curthread) { + if (curthread->unblock_sigcancel) { + sigset_t set; + + SIGEMPTYSET(set); + SIGADDSET(set, SIGCANCEL); + sigprocmask(SIG_UNBLOCK, &set, NULL); + } + if (curthread->attr.suspend == THR_CREATE_SUSPENDED) { sigset_t set = curthread->sigmask; diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index 4db3b7a..ff9f52b 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -378,6 +378,12 @@ struct pthread { /* Thread temporary signal mask. */ sigset_t sigmask; + /* Thread is in SIGCANCEL handler. */ + int in_sigcancel_handler; + + /* New thread should unblock SIGCANCEL. */ + int unblock_sigcancel; + /* Thread state: */ enum pthread_state state; diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c index 6da4b90..c8ebc24 100644 --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -69,7 +69,9 @@ sigcancel_handler(int sig __unused, if (curthread->cancel_defer && curthread->cancel_pending) thr_wake(curthread->tid); + curthread->in_sigcancel_handler = 1; _thr_ast(curthread); + curthread->in_sigcancel_handler = 0; } void |