diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2008-12-16 07:57:29 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2008-12-16 07:57:29 +0000 |
commit | 66f602cf3edb31a30ff3fcee9bd3d4b9d4ff57a7 (patch) | |
tree | 446062b72d3d878e3dd07d974267043287dbbd8b | |
parent | 799c9944fa8bbbc14aab0bb61b58d2823678bc31 (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.c | 14 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 92 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 6 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 4 | ||||
-rw-r--r-- | sys/sys/proc.h | 3 | ||||
-rw-r--r-- | sys/sys/signalvar.h | 5 |
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); |