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;