summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2015-07-28 13:52:29 -0700
committerJoshua M. Clulow <jmc@joyent.com>2015-07-31 22:05:13 +0000
commit0c7cd6a285036e86aa5828b956ceeae268b7c2ca (patch)
treec3d7563d00459c7d821aec1b6b5c0576cab32b24 /usr/src/lib/libc
parentafaff3ad2e43966f17aaa81ff16945cd59170032 (diff)
downloadillumos-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-vers1
-rw-r--r--usr/src/lib/libc/port/threads/sigaction.c42
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;
/*