diff options
author | Joshua M. Clulow <jmc@joyent.com> | 2015-07-28 13:52:29 -0700 |
---|---|---|
committer | Joshua M. Clulow <jmc@joyent.com> | 2015-07-31 22:05:13 +0000 |
commit | 0c7cd6a285036e86aa5828b956ceeae268b7c2ca (patch) | |
tree | c3d7563d00459c7d821aec1b6b5c0576cab32b24 /usr/src/lib/libc | |
parent | afaff3ad2e43966f17aaa81ff16945cd59170032 (diff) | |
download | illumos-joyent-0c7cd6a285036e86aa5828b956ceeae268b7c2ca.tar.gz |
OS-4470 lxbrand unblocking signals in new threads must be atomic
Reviewed by: Robert Mustacchi <rm@joyent.com>
Diffstat (limited to 'usr/src/lib/libc')
-rw-r--r-- | usr/src/lib/libc/port/mapfile-vers | 1 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/sigaction.c | 42 |
2 files changed, 29 insertions, 14 deletions
diff --git a/usr/src/lib/libc/port/mapfile-vers b/usr/src/lib/libc/port/mapfile-vers index 296e49fe3b..6d2a77e1df 100644 --- a/usr/src/lib/libc/port/mapfile-vers +++ b/usr/src/lib/libc/port/mapfile-vers @@ -2973,6 +2973,7 @@ $endif _semctl64; set_escaped_context_cleanup; set_setcontext_enforcement; + setcontext_sigmask; _setbufend; __set_errno; setprojrctl; diff --git a/usr/src/lib/libc/port/threads/sigaction.c b/usr/src/lib/libc/port/threads/sigaction.c index 09be90e54f..ada1afd523 100644 --- a/usr/src/lib/libc/port/threads/sigaction.c +++ b/usr/src/lib/libc/port/threads/sigaction.c @@ -540,6 +540,33 @@ set_setcontext_enforcement(int on) setcontext_enforcement = on; } +/* + * The LX brand emulation library implements an operation that is analogous to + * setcontext(), but takes a different path in to the kernel. So that it can + * correctly restore a signal mask, we expose just the signal mask handling + * part of the regular setcontext() routine as a private interface. + */ +void +setcontext_sigmask(ucontext_t *ucp) +{ + ulwp_t *self = curthread; + + if (ucp->uc_flags & UC_SIGMASK) { + block_all_signals(self); + delete_reserved_signals(&ucp->uc_sigmask); + self->ul_sigmask = ucp->uc_sigmask; + if (self->ul_cursig) { + /* + * We have a deferred signal present. + * The signal mask will be set when the + * signal is taken in take_deferred_signal(). + */ + ASSERT(self->ul_critical + self->ul_sigdefer != 0); + ucp->uc_flags &= ~UC_SIGMASK; + } + } +} + #pragma weak _setcontext = setcontext int setcontext(const ucontext_t *ucp) @@ -560,20 +587,7 @@ setcontext(const ucontext_t *ucp) /* * Restore previous signal mask and context link. */ - if (uc.uc_flags & UC_SIGMASK) { - block_all_signals(self); - delete_reserved_signals(&uc.uc_sigmask); - self->ul_sigmask = uc.uc_sigmask; - if (self->ul_cursig) { - /* - * We have a deferred signal present. - * The signal mask will be set when the - * signal is taken in take_deferred_signal(). - */ - ASSERT(self->ul_critical + self->ul_sigdefer != 0); - uc.uc_flags &= ~UC_SIGMASK; - } - } + setcontext_sigmask(&uc); self->ul_siglink = uc.uc_link; /* |