summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libthr/thread/thr_create.c17
-rw-r--r--lib/libthr/thread/thr_private.h6
-rw-r--r--lib/libthr/thread/thr_sig.c2
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
OpenPOWER on IntegriCloud