Module Name: src Committed By: snj Date: Tue Mar 31 23:41:23 UTC 2009
Modified Files: src/sys/kern [netbsd-5]: kern_sig.c Log Message: Pull up following revision(s) (requested by rmind in ticket #620): sys/kern/kern_sig.c: revision 1.297 kpsignal2: do not start process (when it is stopped) for all termination signals (i.e. SA_KILL), just if SIGKILL (or SIGCONT). Improve comments. Make some functions static, remove unused sigrealloc() prototype. Fixes PR/39814. Similar patch reviewed by <ad>. To generate a diff of this commit: cvs rdiff -u -r1.289.4.3 -r1.289.4.4 src/sys/kern/kern_sig.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_sig.c diff -u src/sys/kern/kern_sig.c:1.289.4.3 src/sys/kern/kern_sig.c:1.289.4.4 --- src/sys/kern/kern_sig.c:1.289.4.3 Mon Feb 2 19:50:20 2009 +++ src/sys/kern/kern_sig.c Tue Mar 31 23:41:23 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_sig.c,v 1.289.4.3 2009/02/02 19:50:20 snj Exp $ */ +/* $NetBSD: kern_sig.c,v 1.289.4.4 2009/03/31 23:41:23 snj Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.289.4.3 2009/02/02 19:50:20 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v 1.289.4.4 2009/03/31 23:41:23 snj Exp $"); #include "opt_ptrace.h" #include "opt_compat_sunos.h" @@ -106,13 +106,11 @@ static void ksiginfo_exechook(struct proc *, void *); static void proc_stop_callout(void *); - -int sigunwait(struct proc *, const ksiginfo_t *); -void sigput(sigpend_t *, struct proc *, ksiginfo_t *); -int sigpost(struct lwp *, sig_t, int, int, int); -int sigchecktrace(void); -void sigswitch(bool, int, int); -void sigrealloc(ksiginfo_t *); +static int sigchecktrace(void); +static int sigpost(struct lwp *, sig_t, int, int, int); +static void sigput(sigpend_t *, struct proc *, ksiginfo_t *); +static int sigunwait(struct proc *, const ksiginfo_t *); +static void sigswitch(bool, int, int); sigset_t contsigmask, stopsigmask, sigcantmask; static pool_cache_t sigacts_cache; /* memory pool for sigacts structures */ @@ -548,7 +546,7 @@ * Append a new ksiginfo element to the list of pending ksiginfo's, if * we need to (e.g. SA_SIGINFO was requested). */ -void +static void sigput(sigpend_t *sp, struct proc *p, ksiginfo_t *ksi) { ksiginfo_t *kp; @@ -883,10 +881,11 @@ KASSERT(!cpu_intr_p()); KASSERT(mutex_owned(proc_lock)); - if (pgrp) - LIST_FOREACH(p, &pgrp->pg_members, p_pglist) - if (checkctty == 0 || p->p_lflag & PL_CONTROLT) - kpsignal(p, ksi, data); + if (__predict_false(pgrp == 0)) + return; + LIST_FOREACH(p, &pgrp->pg_members, p_pglist) + if (checkctty == 0 || p->p_lflag & PL_CONTROLT) + kpsignal(p, ksi, data); } /* @@ -1037,7 +1036,7 @@ * Post a pending signal to an LWP. Returns non-zero if the LWP may * be able to take the signal. */ -int +static int sigpost(struct lwp *l, sig_t action, int prop, int sig, int idlecheck) { int rv, masked; @@ -1069,13 +1068,14 @@ } /* - * SIGCONT can be masked, but must always restart stopped LWPs. + * SIGCONT can be masked, but if LWP is stopped, it needs restart. + * Note: SIGKILL and SIGSTOP cannot be masked. */ #if KERN_SA if (p->p_sa != NULL) masked = sigismember(&p->p_sa->sa_sigmask, sig); else -#endif /* KERN_SA */ +#endif masked = sigismember(&l->l_sigmask, sig); if (masked && ((prop & SA_CONT) == 0 || l->l_stat != LSSTOP)) { lwp_unlock(l); @@ -1173,7 +1173,7 @@ * Find an LWP within process p that is waiting on signal ksi, and hand * it on. */ -int +static int sigunwait(struct proc *p, const ksiginfo_t *ksi) { struct lwp *l; @@ -1388,8 +1388,6 @@ */ if ((prop & SA_CONT) != 0 && action == SIG_DFL) goto out; - - sigput(&p->p_sigpend, p, kp); } else { /* * Process is stopped or stopping. If traced, then no @@ -1398,7 +1396,10 @@ if ((p->p_slflag & PSL_TRACED) != 0 && signo != SIGKILL) goto out; - if ((prop & (SA_CONT | SA_KILL)) != 0) { + /* + * Run the process only if sending SIGCONT or SIGKILL. + */ + if ((prop & SA_CONT) != 0 || signo == SIGKILL) { /* * Re-adjust p_nstopchild if the process wasn't * collected by its parent. @@ -1409,27 +1410,28 @@ p->p_pptr->p_nstopchild--; /* - * If SIGCONT is default (or ignored), we continue - * the process but don't leave the signal in - * ps_siglist, as it has no further action. If - * SIGCONT is held, we continue the process and - * leave the signal in ps_siglist. If the process - * catches SIGCONT, let it handle the signal itself. - * If it isn't waiting on an event, then it goes - * back to run state. Otherwise, process goes back - * to sleep state. + * Do not make signal pending if SIGCONT is default. + * + * If the process catches SIGCONT, let it handle the + * signal itself (if waiting on event - process runs, + * otherwise continues sleeping). */ - if ((prop & SA_CONT) == 0 || action != SIG_DFL) - sigput(&p->p_sigpend, p, kp); + if ((prop & SA_CONT) != 0 && action == SIG_DFL) { + KASSERT(signo != SIGKILL); + goto deliver; + } } else if ((prop & SA_STOP) != 0) { /* * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ goto out; - } else - sigput(&p->p_sigpend, p, kp); + } } + /* + * Make signal pending. + */ + sigput(&p->p_sigpend, p, kp); deliver: /* @@ -1594,7 +1596,7 @@ /* * Stop the current process and switch away when being stopped or traced. */ -void +static void sigswitch(bool ppsig, int ppmask, int signo) { struct lwp *l = curlwp; @@ -1660,7 +1662,7 @@ /* * Check for a signal from the debugger. */ -int +static int sigchecktrace(void) { struct lwp *l = curlwp;