summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorbluhm <bluhm@openbsd.org>2019-05-13 19:21:31 +0000
committerbluhm <bluhm@openbsd.org>2019-05-13 19:21:31 +0000
commit788422d65be41111bc05f25ec194535e3ae7eb6c (patch)
tree2a0e4cfda82fe14e76fd02a67a366b04f0eddc90 /sys/kern
parentDo not check for IFF_RUNNING inside bstp_initialization(). (diff)
downloadwireguard-openbsd-788422d65be41111bc05f25ec194535e3ae7eb6c.tar.xz
wireguard-openbsd-788422d65be41111bc05f25ec194535e3ae7eb6c.zip
When killing a process, the signal is handled by any thread that
does not block the signal. If all threads block the signal, we delivered it to the main thread. This does not conform to POSIX. If any thread unblocks the signal, it should be delivered immediately to this thread. Mark such signals pending at the process instead of a single thread. Then any thread can handle it later. OK kettenis@ guenther@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/exec_elf.c4
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_sig.c54
-rw-r--r--sys/kern/tty.c6
4 files changed, 40 insertions, 28 deletions
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c
index 9d5639a24a7..24adf0dbed6 100644
--- a/sys/kern/exec_elf.c
+++ b/sys/kern/exec_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.c,v 1.150 2019/05/11 19:59:26 deraadt Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.151 2019/05/13 19:21:31 bluhm Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
@@ -1211,7 +1211,7 @@ coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep)
cpi.cpi_signo = p->p_sisig;
cpi.cpi_sigcode = p->p_sicode;
- cpi.cpi_sigpend = p->p_siglist;
+ cpi.cpi_sigpend = p->p_siglist | pr->ps_siglist;
cpi.cpi_sigmask = p->p_sigmask;
cpi.cpi_sigignore = pr->ps_sigacts->ps_sigignore;
cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch;
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 918ea4dc1bd..bff9a2c5ef7 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.173 2019/01/23 22:39:47 tedu Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.174 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -180,6 +180,8 @@ exit1(struct proc *p, int rv, int flags)
}
}
p->p_siglist = 0;
+ if ((p->p_flag & P_THREAD) == 0)
+ pr->ps_siglist = 0;
#if NKCOV > 0
kcov_exit(p);
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);
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index c57e8ca9a4f..fd54b0fca75 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tty.c,v 1.143 2018/09/06 11:50:54 jsg Exp $ */
+/* $OpenBSD: tty.c,v 1.144 2019/05/13 19:21:31 bluhm Exp $ */
/* $NetBSD: tty.c,v 1.68.4.2 1996/06/06 16:04:52 thorpej Exp $ */
/*-
@@ -1676,11 +1676,11 @@ ttycheckoutq(struct tty *tp, int wait)
hiwat = tp->t_hiwat;
s = spltty();
- oldsig = wait ? curproc->p_siglist : 0;
+ oldsig = wait ? SIGPENDING(curproc) : 0;
if (tp->t_outq.c_cc > hiwat + TTHIWATMINSPACE)
while (tp->t_outq.c_cc > hiwat) {
ttstart(tp);
- if (wait == 0 || curproc->p_siglist != oldsig) {
+ if (wait == 0 || SIGPENDING(curproc) != oldsig) {
splx(s);
return (0);
}