diff options
author | davidxu <davidxu@FreeBSD.org> | 2006-02-23 09:24:19 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2006-02-23 09:24:19 +0000 |
commit | 890309fa66ea204800865f48a2fc05aff11ed90c (patch) | |
tree | eebc22de83b31d2a84b0fa93537dc8728f4424f0 /sys/kern | |
parent | 234bd7650da3040c4741a7fd3f2acb9f5b987785 (diff) | |
download | FreeBSD-src-890309fa66ea204800865f48a2fc05aff11ed90c.zip FreeBSD-src-890309fa66ea204800865f48a2fc05aff11ed90c.tar.gz |
1. Refine kern_sigtimedwait() to remove redundant code.
2. Fix a bug, if thread got a SIGKILL signal, call sigexit() to kill
its process.
MFC after: 3 days
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_sig.c | 74 |
1 files changed, 43 insertions, 31 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index ed7a5af..8dfe3f2 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1189,35 +1189,40 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi, } } -again: +restart: for (i = 1; i <= _SIG_MAXSIG; ++i) { if (!SIGISMEMBER(waitset, i)) continue; - if (SIGISMEMBER(td->td_sigqueue.sq_signals, i)) { - SIGFILLSET(td->td_sigmask); - SIG_CANTMASK(td->td_sigmask); - SIGDELSET(td->td_sigmask, i); - mtx_lock(&ps->ps_mtx); - sig = cursig(td); - i = 0; - mtx_unlock(&ps->ps_mtx); - } else if (SIGISMEMBER(p->p_sigqueue.sq_signals, i)) { - if (p->p_flag & P_SA) { - p->p_flag |= P_SIGEVENT; - wakeup(&p->p_siglist); - } - sigqueue_move(&p->p_sigqueue, &td->td_sigqueue, i); - SIGFILLSET(td->td_sigmask); - SIG_CANTMASK(td->td_sigmask); - SIGDELSET(td->td_sigmask, i); - mtx_lock(&ps->ps_mtx); - sig = cursig(td); - i = 0; - mtx_unlock(&ps->ps_mtx); + if (!SIGISMEMBER(td->td_sigqueue.sq_signals, i)) { + if (SIGISMEMBER(p->p_sigqueue.sq_signals, i)) { + if (p->p_flag & P_SA) { + p->p_flag |= P_SIGEVENT; + wakeup(&p->p_siglist); + } + sigqueue_move(&p->p_sigqueue, + &td->td_sigqueue, i); + } else + continue; } + + SIGFILLSET(td->td_sigmask); + SIG_CANTMASK(td->td_sigmask); + SIGDELSET(td->td_sigmask, i); + mtx_lock(&ps->ps_mtx); + sig = cursig(td); + mtx_unlock(&ps->ps_mtx); if (sig) goto out; + else { + /* + * Because cursig() may have stopped current thread, + * after it is resumed, things may have already been + * changed, it should rescan any pending signals. + */ + goto restart; + } } + if (error) goto out; @@ -1255,30 +1260,37 @@ again: error = 0; } } - goto again; + goto restart; out: + td->td_sigmask = savedmask; + signotify(td); if (sig) { - sig_t action; - ksiginfo_init(ksi); sigqueue_get(&td->td_sigqueue, sig, ksi); ksi->ksi_signo = sig; if (ksi->ksi_code == SI_TIMER) itimer_accept(p, ksi->ksi_timerid, ksi); error = 0; - mtx_lock(&ps->ps_mtx); - action = ps->ps_sigact[_SIG_IDX(sig)]; - mtx_unlock(&ps->ps_mtx); + #ifdef KTRACE - if (KTRPOINT(td, KTR_PSIG)) + if (KTRPOINT(td, KTR_PSIG)) { + sig_t action; + + mtx_lock(&ps->ps_mtx); + action = ps->ps_sigact[_SIG_IDX(sig)]; + mtx_unlock(&ps->ps_mtx); ktrpsig(sig, action, &td->td_sigmask, 0); + } #endif _STOPEVENT(p, S_SIG, sig); + if (sig == SIGKILL) { + p->p_code = ksi->ksi_code; + p->p_sig = sig; + sigexit(td, sig); + } } - td->td_sigmask = savedmask; - signotify(td); PROC_UNLOCK(p); return (error); } |