Print this page
OS-4470 lxbrand unblocking signals in new threads must be atomic
*** 538,547 ****
--- 538,574 ----
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)
{
ulwp_t *self = curthread;
*** 558,581 ****
(void) memcpy(&uc, ucp, sizeof (uc));
/*
* 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;
! }
! }
self->ul_siglink = uc.uc_link;
/*
* We don't know where this context structure has been.
* Preserve the curthread pointer, at least.
--- 585,595 ----
(void) memcpy(&uc, ucp, sizeof (uc));
/*
* Restore previous signal mask and context link.
*/
! setcontext_sigmask(&uc);
self->ul_siglink = uc.uc_link;
/*
* We don't know where this context structure has been.
* Preserve the curthread pointer, at least.