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;

Reply via email to