PassOwnPtr<Syscall> SigprocmaskSyscall::createFromContext(ucontext_t* ucontext) { // This syscall is never proxied to the broker process and resolved locally. // What we do here is silently remove SIGSYS from the signal set so no // thread will ever be able to block it. ASSERT(ucontext); mcontext_t mcontext = ucontext->uc_mcontext; int how = mcontext.gregs[REG_ARG0]; sigset_t* set = reinterpret_cast<sigset_t*>(mcontext.gregs[REG_ARG1]); sigset_t* oldSet = reinterpret_cast<sigset_t*>(mcontext.gregs[REG_ARG2]); if (oldSet) memcpy(oldSet, &ucontext->uc_sigmask, sizeof(sigset_t)); if (how == SIG_SETMASK) memcpy(&ucontext->uc_sigmask, set, sizeof(sigset_t)); else sigorset(&ucontext->uc_sigmask, set, &ucontext->uc_sigmask); sigdelset(&ucontext->uc_sigmask, SIGSYS); mcontext.gregs[REG_SYSCALL] = 0; return nullptr; }
sigset_t sigset_or(sigset_t a, sigset_t b) { int status; sigset_t result; status = sigemptyset(&result); ASSUME(status, 0); status = sigorset(&result, &a, &b); ASSUME(status, 0); return result; }
//----------------------------------------------------------------------- //----------------------------------------------------------------------- RtSigSet RtSigSet::operator| (const RtSigSet& sigset) { RtSigSet result; sigorset (&result, this, &sigset); return result; }
/* * Common code for calling the user-specified signal handler. */ void call_user_handler(int sig, siginfo_t *sip, ucontext_t *ucp) { ulwp_t *self = curthread; uberdata_t *udp = self->ul_uberdata; struct sigaction uact; volatile struct sigaction *sap; /* * If we are taking a signal while parked or about to be parked * on __lwp_park() then remove ourself from the sleep queue so * that we can grab locks. The code in mutex_lock_queue() and * cond_wait_common() will detect this and deal with it when * __lwp_park() returns. */ unsleep_self(); set_parking_flag(self, 0); if (__td_event_report(self, TD_CATCHSIG, udp)) { self->ul_td_evbuf.eventnum = TD_CATCHSIG; self->ul_td_evbuf.eventdata = (void *)(intptr_t)sig; tdb_event(TD_CATCHSIG, udp); } /* * Get a self-consistent set of flags, handler, and mask * while holding the sig's sig_lock for the least possible time. * We must acquire the sig's sig_lock because some thread running * in sigaction() might be establishing a new signal handler. * The code in sigaction() acquires the writer lock; here * we acquire the readers lock to ehance concurrency in the * face of heavy signal traffic, such as generated by java. * * Locking exceptions: * No locking for a child of vfork(). * If the signal is SIGPROF with an si_code of PROF_SIG, * then we assume that this signal was generated by * setitimer(ITIMER_REALPROF) set up by the dbx collector. * If the signal is SIGEMT with an si_code of EMT_CPCOVF, * then we assume that the signal was generated by * a hardware performance counter overflow. * In these cases, assume that we need no locking. It is the * monitoring program's responsibility to ensure correctness. */ sap = &udp->siguaction[sig].sig_uaction; if (self->ul_vfork || (sip != NULL && ((sig == SIGPROF && sip->si_code == PROF_SIG) || (sig == SIGEMT && sip->si_code == EMT_CPCOVF)))) { /* we wish this assignment could be atomic */ (void) memcpy(&uact, (void *)sap, sizeof (uact)); } else { rwlock_t *rwlp = &udp->siguaction[sig].sig_lock; lrw_rdlock(rwlp); (void) memcpy(&uact, (void *)sap, sizeof (uact)); if ((sig == SIGCANCEL || sig == SIGAIOCANCEL) && (sap->sa_flags & SA_RESETHAND)) sap->sa_sigaction = SIG_DFL; lrw_unlock(rwlp); } /* * Set the proper signal mask and call the user's signal handler. * (We overrode the user-requested signal mask with maskset * so we currently have all blockable signals blocked.) * * We would like to ASSERT() that the signal is not a member of the * signal mask at the previous level (ucp->uc_sigmask) or the specified * signal mask for sigsuspend() or pollsys() (self->ul_tmpmask) but * /proc can override this via PCSSIG, so we don't bother. * * We would also like to ASSERT() that the signal mask at the previous * level equals self->ul_sigmask (maskset for sigsuspend() / pollsys()), * but /proc can change the thread's signal mask via PCSHOLD, so we * don't bother with that either. */ ASSERT(ucp->uc_flags & UC_SIGMASK); if (self->ul_sigsuspend) { ucp->uc_sigmask = self->ul_sigmask; self->ul_sigsuspend = 0; /* the sigsuspend() or pollsys() signal mask */ sigorset(&uact.sa_mask, &self->ul_tmpmask); } else { /* the signal mask at the previous level */ sigorset(&uact.sa_mask, &ucp->uc_sigmask); } if (!(uact.sa_flags & SA_NODEFER)) /* add current signal */ (void) sigaddset(&uact.sa_mask, sig); self->ul_sigmask = uact.sa_mask; self->ul_siglink = ucp; (void) __lwp_sigmask(SIG_SETMASK, &uact.sa_mask); /* * If this thread has been sent SIGCANCEL from the kernel * or from pthread_cancel(), it is being asked to exit. * The kernel may send SIGCANCEL without a siginfo struct. * If the SIGCANCEL is process-directed (from kill() or * sigqueue()), treat it as an ordinary signal. */ if (sig == SIGCANCEL) { if (sip == NULL || SI_FROMKERNEL(sip) || sip->si_code == SI_LWP) { do_sigcancel(); goto out; } /* SIGCANCEL is ignored by default */ if (uact.sa_sigaction == SIG_DFL || uact.sa_sigaction == SIG_IGN) goto out; } /* * If this thread has been sent SIGAIOCANCEL (SIGLWP) and * we are an aio worker thread, cancel the aio request. */ if (sig == SIGAIOCANCEL) { aio_worker_t *aiowp = pthread_getspecific(_aio_key); if (sip != NULL && sip->si_code == SI_LWP && aiowp != NULL) siglongjmp(aiowp->work_jmp_buf, 1); /* SIGLWP is ignored by default */ if (uact.sa_sigaction == SIG_DFL || uact.sa_sigaction == SIG_IGN) goto out; } if (!(uact.sa_flags & SA_SIGINFO)) sip = NULL; __sighndlr(sig, sip, ucp, uact.sa_sigaction); #if defined(sparc) || defined(__sparc) /* * If this is a floating point exception and the queue * is non-empty, pop the top entry from the queue. This * is to maintain expected behavior. */ if (sig == SIGFPE && ucp->uc_mcontext.fpregs.fpu_qcnt) { fpregset_t *fp = &ucp->uc_mcontext.fpregs; if (--fp->fpu_qcnt > 0) { unsigned char i; struct fq *fqp; fqp = fp->fpu_q; for (i = 0; i < fp->fpu_qcnt; i++) fqp[i] = fqp[i+1]; } } #endif /* sparc */ out: (void) setcontext(ucp); thr_panic("call_user_handler(): setcontext() returned"); }