diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-05-08 13:05:34 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2024-05-08 13:05:34 +0000 |
commit | 72fb29dace371c75dac3860077e9e6650efd4328 (patch) | |
tree | f2d60139a5ef19d8beef6305b2938d46245aa1a4 /sys | |
parent | 507eb50bcecdae44fba3f6d486aaef0de67f21f2 (diff) |
Rework how action SIG_HOLD is handled in ptsignal.
Since we want to unlock sigsuspend, ptsignal needs to double check in the
SSLEEP case that the signal being delivered is still masked or unmasked.
Remove the early return for action SIG_HOLD so that the SSLEEP case can
properly recheck the sigmask.
On top of this update siglist only in one place at the end of ptsignal
this now includes the clearing of signals for the SA_CONT and SA_STOP
cases.
OK mpi@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_sig.c | 62 |
1 files changed, 42 insertions, 20 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 1a022be4070..d5b896cbfed 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.326 2024/05/07 10:46:35 claudio Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.327 2024/05/08 13:05:33 claudio Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -921,7 +921,7 @@ void ptsignal(struct proc *p, int signum, enum signal_type type) { int s, prop; - sig_t action; + sig_t action, altaction = SIG_DFL; sigset_t mask, sigmask; int *siglist; struct process *pr = p->p_p; @@ -1026,6 +1026,8 @@ ptsignal(struct proc *p, int signum, enum signal_type type) return; if (sigmask & mask) { action = SIG_HOLD; + if (sigcatch & mask) + altaction = SIG_CATCH; } else if (sigcatch & mask) { action = SIG_CATCH; } else { @@ -1050,15 +1052,8 @@ ptsignal(struct proc *p, int signum, enum signal_type type) * marked at thread level. */ siglist = (type == SPROCESS) ? &pr->ps_siglist : &p->p_siglist; - if (prop & SA_CONT) { - siglist = &p->p_siglist; - atomic_clearbits_int(siglist, STOPSIGMASK); - } - if (prop & SA_STOP) { + if (prop & (SA_CONT | SA_STOP)) siglist = &p->p_siglist; - atomic_clearbits_int(siglist, CONTSIGMASK); - atomic_clearbits_int(&p->p_flag, P_CONTINUED); - } /* * XXX delay processing of SA_STOP signals unless action == SIG_DFL? @@ -1068,16 +1063,6 @@ ptsignal(struct proc *p, int signum, enum signal_type type) if (q != p) ptsignal(q, signum, SPROPAGATED); - /* - * Defer further processing for signals which are held, - * except that stopped processes must be continued by SIGCONT. - */ - if (action == SIG_HOLD && ((prop & SA_CONT) == 0 || - p->p_stat != SSTOP)) { - atomic_setbits_int(siglist, mask); - return; - } - SCHED_LOCK(s); switch (p->p_stat) { @@ -1107,6 +1092,25 @@ ptsignal(struct proc *p, int signum, enum signal_type type) sigmask = READ_ONCE(p->p_sigmask); if (sigmask & mask) goto out; + else if (action == SIG_HOLD) { + /* signal got unmasked, get proper action */ + action = altaction; + + if (action == SIG_DFL) { + if (prop & SA_KILL && pr->ps_nice > NZERO) + pr->ps_nice = NZERO; + + /* + * Discard tty stop signals sent to an + * orphaned process group, see above. + */ + if (prop & SA_TTYSTOP && + pr->ps_pgrp->pg_jobc == 0) { + SCHED_UNLOCK(s); + return; + } + } + } /* * If SIGCONT is default (or ignored) and process is @@ -1181,6 +1185,13 @@ ptsignal(struct proc *p, int signum, enum signal_type type) goto out; } + /* + * Defer further processing for signals which are held, + * except that stopped processes must be continued by SIGCONT. + */ + if (action == SIG_HOLD) + goto out; + if (prop & SA_STOP) { /* * Already stopped, don't need to stop again. @@ -1201,6 +1212,9 @@ ptsignal(struct proc *p, int signum, enum signal_type type) goto out; case SONPROC: + if (action == SIG_HOLD) + goto out; + /* set siglist before issuing the ast */ atomic_setbits_int(siglist, mask); mask = 0; @@ -1229,6 +1243,14 @@ out: /* finally adjust siglist */ if (mask) atomic_setbits_int(siglist, mask); + if (prop & SA_CONT) { + atomic_clearbits_int(siglist, STOPSIGMASK); + } + if (prop & SA_STOP) { + atomic_clearbits_int(siglist, CONTSIGMASK); + atomic_clearbits_int(&p->p_flag, P_CONTINUED); + } + SCHED_UNLOCK(s); if (wakeparent) wakeup(pr->ps_pptr); |