-/* $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 $ */
/*
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;
return;
if (sigmask & mask) {
action = SIG_HOLD;
+ if (sigcatch & mask)
+ altaction = SIG_CATCH;
} else if (sigcatch & mask) {
action = SIG_CATCH;
} else {
* 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?
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) {
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
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.
goto out;
case SONPROC:
+ if (action == SIG_HOLD)
+ goto out;
+
/* set siglist before issuing the ast */
atomic_setbits_int(siglist, mask);
mask = 0;
/* 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);