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 /sys/kern/kern_sig.c | |
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@
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r-- | sys/kern/kern_sig.c | 92 |
1 files changed, 64 insertions, 28 deletions
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); } |