summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c54
1 files changed, 32 insertions, 22 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index fc538174c1a..4e3efa9c736 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.229 2019/05/01 06:26:42 dlg Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.230 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -364,7 +364,8 @@ setsigvec(struct proc *p, int signum, struct sigaction *sa)
*/
if (sa->sa_handler == SIG_IGN ||
(sigprop[signum] & SA_IGNORE && sa->sa_handler == SIG_DFL)) {
- atomic_clearbits_int(&p->p_siglist, bit);
+ atomic_clearbits_int(&p->p_siglist, bit);
+ atomic_clearbits_int(&p->p_p->ps_siglist, bit);
if (signum != SIGCONT)
ps->ps_sigignore |= bit; /* easier in psignal */
ps->ps_sigcatch &= ~bit;
@@ -419,6 +420,7 @@ execsigs(struct proc *p)
if (nc != SIGCONT)
ps->ps_sigignore |= mask;
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
}
ps->ps_sigact[nc] = SIG_DFL;
}
@@ -472,7 +474,7 @@ int
sys_sigpending(struct proc *p, void *v, register_t *retval)
{
- *retval = p->p_siglist;
+ *retval = p->p_siglist | p->p_p->ps_siglist;
return (0);
}
@@ -875,7 +877,6 @@ psignal(struct proc *p, int signum)
/*
* type = SPROCESS process signal, can be diverted (sigwait())
- * XXX if blocked in all threads, mark as pending in struct process
* type = STHREAD thread signal, but should be propagated if unhandled
* type = SPROPAGATED propagated to this thread, so don't propagate again
*/
@@ -885,6 +886,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
int s, prop;
sig_t action;
int mask;
+ int *siglist;
struct process *pr = p->p_p;
struct proc *q;
int wakeparent = 0;
@@ -907,7 +909,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
if (pr->ps_flags & PS_COREDUMP && signum == SIGKILL) {
if (pr->ps_single != NULL)
p = pr->ps_single;
- atomic_setbits_int(&p->p_siglist, mask);
+ atomic_setbits_int(&p->p_p->ps_siglist, mask);
return;
}
@@ -962,7 +964,6 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
*/
if (pr->ps_flags & PS_TRACED) {
action = SIG_DFL;
- atomic_setbits_int(&p->p_siglist, mask);
} else {
/*
* If the signal is being ignored,
@@ -992,17 +993,23 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
if (prop & SA_TTYSTOP && pr->ps_pgrp->pg_jobc == 0)
return;
}
-
- atomic_setbits_int(&p->p_siglist, mask);
}
-
- if (prop & SA_CONT)
- atomic_clearbits_int(&p->p_siglist, stopsigmask);
-
+ /*
+ * If delivered to process, mark as pending there. Continue and stop
+ * signals will be propagated to all threads. So they are always
+ * 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) {
- atomic_clearbits_int(&p->p_siglist, contsigmask);
+ siglist = &p->p_siglist;
+ atomic_clearbits_int(siglist, contsigmask);
atomic_clearbits_int(&p->p_flag, P_CONTINUED);
}
+ atomic_setbits_int(siglist, mask);
/*
* XXX delay processing of SA_STOP signals unless action == SIG_DFL?
@@ -1045,7 +1052,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* be awakened.
*/
if ((prop & SA_CONT) && action == SIG_DFL) {
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
goto out;
}
/*
@@ -1059,7 +1066,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
*/
if (pr->ps_flags & PS_PPWAIT)
goto out;
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
p->p_xstat = signum;
proc_stop(p, 0);
goto out;
@@ -1102,7 +1109,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
atomic_clearbits_int(&p->p_flag, P_SUSPSIG);
wakeparent = 1;
if (action == SIG_DFL)
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
if (action == SIG_CATCH)
goto runfast;
if (p->p_wchan == 0)
@@ -1116,7 +1123,7 @@ ptsignal(struct proc *p, int signum, enum signal_type type)
* Already stopped, don't need to stop again.
* (If we did the shell could get confused.)
*/
- atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(siglist, mask);
goto out;
}
@@ -1181,7 +1188,7 @@ issignal(struct proc *p)
int s;
for (;;) {
- mask = p->p_siglist & ~p->p_sigmask;
+ mask = SIGPENDING(p);
if (pr->ps_flags & PS_PPWAIT)
mask &= ~stopsigmask;
if (mask == 0) /* no signal to send */
@@ -1189,6 +1196,7 @@ issignal(struct proc *p)
signum = ffs((long)mask);
mask = sigmask(signum);
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
/*
* We should see pending but ignored signals
@@ -1243,6 +1251,7 @@ issignal(struct proc *p)
/* take the signal! */
atomic_clearbits_int(&p->p_siglist, mask);
+ atomic_clearbits_int(&p->p_p->ps_siglist, mask);
}
prop = sigprop[signum];
@@ -1638,7 +1647,8 @@ coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len)
csize = len;
do {
- if (io->io_proc->p_siglist & sigmask(SIGKILL))
+ if (sigmask(SIGKILL) &
+ (io->io_proc->p_siglist | io->io_proc->p_p->ps_siglist))
return (EINTR);
/* Rest of the loop sleeps with lock held, so... */
@@ -1740,8 +1750,8 @@ sys___thrsigdivert(struct proc *p, void *v, register_t *retval)
if (smask & mask) {
if (p->p_siglist & smask)
m = &p->p_siglist;
- else if (pr->ps_mainproc->p_siglist & smask)
- m = &pr->ps_mainproc->p_siglist;
+ else if (pr->ps_siglist & smask)
+ m = &pr->ps_siglist;
else {
/* signal got eaten by someone else? */
continue;
@@ -1868,7 +1878,7 @@ userret(struct proc *p)
KERNEL_UNLOCK();
}
- if (SIGPENDING(p)) {
+ if (SIGPENDING(p) != 0) {
KERNEL_LOCK();
while ((signum = CURSIG(p)) != 0)
postsig(p, signum);