summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2024-05-08 13:05:34 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2024-05-08 13:05:34 +0000
commit72fb29dace371c75dac3860077e9e6650efd4328 (patch)
treef2d60139a5ef19d8beef6305b2938d46245aa1a4 /sys
parent507eb50bcecdae44fba3f6d486aaef0de67f21f2 (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.c62
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);