summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2008-12-16 07:57:29 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2008-12-16 07:57:29 +0000
commit66f602cf3edb31a30ff3fcee9bd3d4b9d4ff57a7 (patch)
tree446062b72d3d878e3dd07d974267043287dbbd8b
parent799c9944fa8bbbc14aab0bb61b58d2823678bc31 (diff)
Move the functionality of psignal() to a new function ptsignal()
that takes an additional argument "type" that indicates whether the signal is for the process, just a particular thread, or propagated to a thread because it's not caught or blocked. psignal() becomes a wrapper that does the first of those. So that sys_kill() can tell apart signals for the process and signals for the process's original thread, the tid of the original thread is defined as its pid + THREAD_PID_OFFSET. ok tedu@ art@ andreas@ kurt@ "better early than late" deraadt@
-rw-r--r--sys/kern/kern_exit.c14
-rw-r--r--sys/kern/kern_prot.c4
-rw-r--r--sys/kern/kern_sig.c92
-rw-r--r--sys/kern/sys_generic.c6
-rw-r--r--sys/kern/uipc_syscalls.c4
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/sys/signalvar.h5
7 files changed, 85 insertions, 43 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 039771ebd76..0677b9ea5dd 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.81 2008/12/11 16:31:47 deraadt Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.82 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -97,7 +97,9 @@ sys_exit(struct proc *p, void *v, register_t *retval)
int
sys_threxit(struct proc *p, void *v, register_t *retval)
{
- struct sys_threxit_args *uap = v;
+ struct sys_threxit_args /* {
+ syscallarg(int) rval;
+ } */ *uap = v;
exit1(p, W_EXITCODE(SCARG(uap, rval), 0), EXIT_THREAD);
@@ -129,7 +131,7 @@ exit1(struct proc *p, int rv, int flags)
* we have to be careful not to get recursively caught.
* this is kinda sick.
*/
- if (flags == EXIT_NORMAL && p->p_p->ps_mainproc != p &&
+ if (flags == EXIT_NORMAL && (p->p_flag & P_THREAD) &&
(p->p_p->ps_mainproc->p_flag & P_WEXIT) == 0) {
/*
* we are one of the threads. we SIGKILL the parent,
@@ -137,9 +139,9 @@ exit1(struct proc *p, int rv, int flags)
*/
atomic_setbits_int(&p->p_p->ps_mainproc->p_flag, P_IGNEXITRV);
p->p_p->ps_mainproc->p_xstat = rv;
- psignal(p->p_p->ps_mainproc, SIGKILL);
+ ptsignal(p->p_p->ps_mainproc, SIGKILL, SPROPAGATED);
tsleep(p->p_p, PUSER, "thrdying", 0);
- } else if (p == p->p_p->ps_mainproc) {
+ } else if ((p->p_flag & P_THREAD) == 0) {
atomic_setbits_int(&p->p_flag, P_WEXIT);
if (flags == EXIT_NORMAL) {
q = TAILQ_FIRST(&p->p_p->ps_threads);
@@ -147,7 +149,7 @@ exit1(struct proc *p, int rv, int flags)
nq = TAILQ_NEXT(q, p_thr_link);
atomic_setbits_int(&q->p_flag, P_IGNEXITRV);
q->p_xstat = rv;
- psignal(q, SIGKILL);
+ ptsignal(q, SIGKILL, SPROPAGATED);
}
}
wakeup(p->p_p);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 4b0185952e2..993f45445ba 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_prot.c,v 1.37 2008/11/01 05:59:21 deraadt Exp $ */
+/* $OpenBSD: kern_prot.c,v 1.38 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */
/*
@@ -77,7 +77,7 @@ sys_getthrid(p, v, retval)
register_t *retval;
{
- *retval = p->p_pid;
+ *retval = p->p_pid + (p->p_flag & P_THREAD ? 0 : THREAD_PID_OFFSET);
return (0);
}
#endif
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 7fe57337454..63d01e252c1 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.100 2008/10/03 04:22:37 guenther Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.101 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -577,13 +577,32 @@ sys_kill(struct proc *cp, void *v, register_t *retval)
if ((u_int)SCARG(uap, signum) >= NSIG)
return (EINVAL);
if (SCARG(uap, pid) > 0) {
+ enum signal_type type = SPROCESS;
+
+#ifdef RTHREADS
+ if (SCARG(uap, pid) > THREAD_PID_OFFSET) {
+ if ((p = pfind(SCARG(uap, pid)
+ - THREAD_PID_OFFSET)) == NULL)
+ return (ESRCH);
+ if (p->p_flag & P_THREAD)
+ return (ESRCH);
+ type = STHREAD;
+ } else
+#endif
+ {
+ if ((p = pfind(SCARG(uap, pid))) == NULL)
+ return (ESRCH);
+#ifdef RTHREADS
+ if (p->p_flag & P_THREAD)
+ type = STHREAD;
+#endif
+ }
+
/* kill single process */
- if ((p = pfind(SCARG(uap, pid))) == NULL)
- return (ESRCH);
if (!cansignal(cp, pc, p, SCARG(uap, signum)))
return (EPERM);
if (SCARG(uap, signum))
- psignal(p, SCARG(uap, signum));
+ ptsignal(p, SCARG(uap, signum), type);
return (0);
}
switch (SCARG(uap, pid)) {
@@ -614,7 +633,7 @@ killpg1(struct proc *cp, int signum, int pgid, int all)
* broadcast
*/
LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
+ if (p->p_pid <= 1 || p->p_flag & (P_SYSTEM|P_THREAD) ||
p == cp || !cansignal(cp, pc, p, signum))
continue;
nfound++;
@@ -633,7 +652,7 @@ killpg1(struct proc *cp, int signum, int pgid, int all)
return (ESRCH);
}
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
+ if (p->p_pid <= 1 || p->p_flag & (P_SYSTEM|P_THREAD) ||
!cansignal(cp, pc, p, signum))
continue;
nfound++;
@@ -747,7 +766,7 @@ trapsignal(struct proc *p, int signum, u_long code, int type,
ps->ps_code = code; /* XXX for core dump/debugger */
ps->ps_type = type;
ps->ps_sigval = sigval;
- psignal(p, signum);
+ ptsignal(p, signum, STHREAD);
}
}
@@ -767,6 +786,18 @@ trapsignal(struct proc *p, int signum, u_long code, int type,
void
psignal(struct proc *p, int signum)
{
+ ptsignal(p, signum, SPROCESS);
+}
+
+/*
+ * 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
+ */
+void
+ptsignal(struct proc *p, int signum, enum signal_type type)
+{
int s, prop;
sig_t action;
int mask;
@@ -787,17 +818,23 @@ psignal(struct proc *p, int signum)
mask = sigmask(signum);
#ifdef RTHREADS
- TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
- if (q == p)
- continue;
- if (q->p_sigdivert & mask) {
- psignal(q, signum);
- return;
+ if (type == SPROCESS) {
+ TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
+ /* ignore exiting threads */
+ if (q->p_flag & P_WEXIT)
+ continue;
+ if (q->p_sigdivert & mask) {
+ /* sigwait: convert to thread-specific */
+ type = STHREAD;
+ p = q;
+ break;
+ }
}
}
#endif
- KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
+ if (type != SPROPAGATED)
+ KNOTE(&p->p_klist, NOTE_SIGNAL | signum);
prop = sigprop[signum];
@@ -846,29 +883,28 @@ psignal(struct proc *p, int signum)
}
if (prop & SA_CONT) {
-#ifdef RTHREADS
- TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
- if (q != p)
- psignal(q, signum);
- }
-#endif
atomic_clearbits_int(&p->p_siglist, stopsigmask);
}
if (prop & SA_STOP) {
-#ifdef RTHREADS
-
- TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
- if (q != p)
- psignal(q, signum);
- }
-#endif
atomic_clearbits_int(&p->p_siglist, contsigmask);
atomic_clearbits_int(&p->p_flag, P_CONTINUED);
}
atomic_setbits_int(&p->p_siglist, mask);
+#ifdef RTHREADS
+ /*
+ * XXX delay processing of SA_STOP signals unless action == SIG_DFL?
+ */
+ if (prop & (SA_CONT | SA_STOP) && type != SPROPAGATED) {
+ TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
+ if (q != p)
+ ptsignal(q, signum, SPROPAGATED);
+ }
+ }
+#endif
+
/*
* Defer further processing for signals which are held,
* except that stopped processes must be continued by SIGCONT.
@@ -1459,7 +1495,7 @@ int
sys_nosys(struct proc *p, void *v, register_t *retval)
{
- psignal(p, SIGSYS);
+ ptsignal(p, SIGSYS, STHREAD);
return (ENOSYS);
}
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index bfcf380a001..ac9d89dd38d 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sys_generic.c,v 1.58 2007/09/07 15:00:20 art Exp $ */
+/* $OpenBSD: sys_generic.c,v 1.59 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */
/*
@@ -337,7 +337,7 @@ dofilewrite(struct proc *p, int fd, struct file *fp, const void *buf,
error == EINTR || error == EWOULDBLOCK))
error = 0;
if (error == EPIPE)
- psignal(p, SIGPIPE);
+ ptsignal(p, SIGPIPE, STHREAD);
}
cnt -= auio.uio_resid;
@@ -448,7 +448,7 @@ dofilewritev(struct proc *p, int fd, struct file *fp, const struct iovec *iovp,
error == EINTR || error == EWOULDBLOCK))
error = 0;
if (error == EPIPE)
- psignal(p, SIGPIPE);
+ ptsignal(p, SIGPIPE, STHREAD);
}
cnt -= auio.uio_resid;
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 288f69c2097..cf19553804f 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_syscalls.c,v 1.68 2008/05/23 15:51:12 thib Exp $ */
+/* $OpenBSD: uipc_syscalls.c,v 1.69 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */
/*
@@ -523,7 +523,7 @@ sendit(struct proc *p, int s, struct msghdr *mp, int flags, register_t *retsize)
error == EINTR || error == EWOULDBLOCK))
error = 0;
if (error == EPIPE)
- psignal(p, SIGPIPE);
+ ptsignal(p, SIGPIPE, STHREAD);
}
if (error == 0) {
*retsize = len - auio.uio_resid;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index da083ee9377..d50bcdfc9b7 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.110 2008/11/07 02:22:33 deraadt Exp $ */
+/* $OpenBSD: proc.h,v 1.111 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -350,6 +350,7 @@ struct uidinfo *uid_find(uid_t);
*/
#define PID_MAX 32766
#define NO_PID (PID_MAX+1)
+#define THREAD_PID_OFFSET 1000000
#define SESS_LEADER(p) ((p)->p_session->s_leader == (p))
#define SESSHOLD(s) ((s)->s_count++)
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 8853ab2c6f2..0e9b0423344 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: signalvar.h,v 1.16 2007/02/06 18:42:37 art Exp $ */
+/* $OpenBSD: signalvar.h,v 1.17 2008/12/16 07:57:28 guenther Exp $ */
/* $NetBSD: signalvar.h,v 1.17 1996/04/22 01:23:31 christos Exp $ */
/*
@@ -149,6 +149,8 @@ int sigprop[NSIG + 1] = {
#define sigcantmask (sigmask(SIGKILL) | sigmask(SIGSTOP))
#ifdef _KERNEL
+enum signal_type { SPROCESS, STHREAD, SPROPAGATED };
+
/*
* Machine-independent functions:
*/
@@ -160,6 +162,7 @@ int issignal(struct proc *p);
void pgsignal(struct pgrp *pgrp, int sig, int checkctty);
void postsig(int sig);
void psignal(struct proc *p, int sig);
+void ptsignal(struct proc *p, int sig, enum signal_type type);
void siginit(struct proc *p);
void trapsignal(struct proc *p, int sig, u_long code, int type,
union sigval val);