Print this page
OS-4470 lxbrand unblocking signals in new threads must be atomic

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libc/port/threads/sigaction.c
          +++ new/usr/src/lib/libc/port/threads/sigaction.c
↓ open down ↓ 532 lines elided ↑ open up ↑
 533  533   * on return from a signal handler via the passed ucontext_t.)
 534  534   */
 535  535  static int setcontext_enforcement = 1;
 536  536  
 537  537  void
 538  538  set_setcontext_enforcement(int on)
 539  539  {
 540  540          setcontext_enforcement = on;
 541  541  }
 542  542  
      543 +/*
      544 + * The LX brand emulation library implements an operation that is analogous to
      545 + * setcontext(), but takes a different path in to the kernel.  So that it can
      546 + * correctly restore a signal mask, we expose just the signal mask handling
      547 + * part of the regular setcontext() routine as a private interface.
      548 + */
      549 +void
      550 +setcontext_sigmask(ucontext_t *ucp)
      551 +{
      552 +        ulwp_t *self = curthread;
      553 +
      554 +        if (ucp->uc_flags & UC_SIGMASK) {
      555 +                block_all_signals(self);
      556 +                delete_reserved_signals(&ucp->uc_sigmask);
      557 +                self->ul_sigmask = ucp->uc_sigmask;
      558 +                if (self->ul_cursig) {
      559 +                        /*
      560 +                         * We have a deferred signal present.
      561 +                         * The signal mask will be set when the
      562 +                         * signal is taken in take_deferred_signal().
      563 +                         */
      564 +                        ASSERT(self->ul_critical + self->ul_sigdefer != 0);
      565 +                        ucp->uc_flags &= ~UC_SIGMASK;
      566 +                }
      567 +        }
      568 +}
      569 +
 543  570  #pragma weak _setcontext = setcontext
 544  571  int
 545  572  setcontext(const ucontext_t *ucp)
 546  573  {
 547  574          ulwp_t *self = curthread;
 548  575          uberdata_t *udp = self->ul_uberdata;
 549  576          int ret;
 550  577          ucontext_t uc;
 551  578  
 552  579          /*
 553  580           * Returning from the main context (uc_link == NULL) causes
 554  581           * the thread to exit.  See setcontext(2) and makecontext(3C).
 555  582           */
 556  583          if (ucp == NULL)
 557  584                  thr_exit(NULL);
 558  585          (void) memcpy(&uc, ucp, sizeof (uc));
 559  586  
 560  587          /*
 561  588           * Restore previous signal mask and context link.
 562  589           */
 563      -        if (uc.uc_flags & UC_SIGMASK) {
 564      -                block_all_signals(self);
 565      -                delete_reserved_signals(&uc.uc_sigmask);
 566      -                self->ul_sigmask = uc.uc_sigmask;
 567      -                if (self->ul_cursig) {
 568      -                        /*
 569      -                         * We have a deferred signal present.
 570      -                         * The signal mask will be set when the
 571      -                         * signal is taken in take_deferred_signal().
 572      -                         */
 573      -                        ASSERT(self->ul_critical + self->ul_sigdefer != 0);
 574      -                        uc.uc_flags &= ~UC_SIGMASK;
 575      -                }
 576      -        }
      590 +        setcontext_sigmask(&uc);
 577  591          self->ul_siglink = uc.uc_link;
 578  592  
 579  593          /*
 580  594           * We don't know where this context structure has been.
 581  595           * Preserve the curthread pointer, at least.
 582  596           *
 583  597           * Allow this feature to be disabled if a particular process
 584  598           * requests it.
 585  599           */
 586  600          if (setcontext_enforcement) {
↓ open down ↓ 204 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX