svn commit: r240467 - head/sys/kern

John Baldwin jhb at FreeBSD.org
Thu Sep 13 15:51:18 UTC 2012


Author: jhb
Date: Thu Sep 13 15:51:18 2012
New Revision: 240467
URL: http://svn.freebsd.org/changeset/base/240467

Log:
  Ignore stop and continue signals sent to an exiting process.  Stop signals
  set p_xstat to the signal that triggered the stop, but p_xstat is also
  used to hold the exit status of an exiting process.  Without this change,
  a stop signal that arrived after a process was marked P_WEXIT but before
  it was marked a zombie would overwrite the exit status with the stop signal
  number.
  
  Reviewed by:	kib
  MFC after:	1 week

Modified:
  head/sys/kern/kern_exit.c
  head/sys/kern/kern_sig.c

Modified: head/sys/kern/kern_exit.c
==============================================================================
--- head/sys/kern/kern_exit.c	Thu Sep 13 14:40:24 2012	(r240466)
+++ head/sys/kern/kern_exit.c	Thu Sep 13 15:51:18 2012	(r240467)
@@ -200,6 +200,14 @@ exit1(struct thread *td, int rv)
 	_STOPEVENT(p, S_EXIT, rv);
 
 	/*
+	 * Ignore any pending request to stop due to a stop signal.
+	 * Once P_WEXIT is set, future requests will be ignored as
+	 * well.
+	 */
+	p->p_flag &= ~P_STOPPED_SIG;
+	KASSERT(!P_SHOULDSTOP(p), ("exiting process is stopped"));
+
+	/*
 	 * Note that we are exiting and do another wakeup of anyone in
 	 * PIOCWAIT in case they aren't listening for S_EXIT stops or
 	 * decided to wait again after we told them we are exiting.

Modified: head/sys/kern/kern_sig.c
==============================================================================
--- head/sys/kern/kern_sig.c	Thu Sep 13 14:40:24 2012	(r240466)
+++ head/sys/kern/kern_sig.c	Thu Sep 13 15:51:18 2012	(r240467)
@@ -2134,6 +2134,8 @@ tdsendsignal(struct proc *p, struct thre
 	 * We try do the per-process part here.
 	 */
 	if (P_SHOULDSTOP(p)) {
+		KASSERT(!(p->p_flag & P_WEXIT),
+		    ("signal to stopped but exiting process"));
 		if (sig == SIGKILL) {
 			/*
 			 * If traced process is already stopped,
@@ -2248,7 +2250,7 @@ tdsendsignal(struct proc *p, struct thre
 		MPASS(action == SIG_DFL);
 
 		if (prop & SA_STOP) {
-			if (p->p_flag & P_PPWAIT)
+			if (p->p_flag & (P_PPWAIT|P_WEXIT))
 				goto out;
 			p->p_flag |= P_STOPPED_SIG;
 			p->p_xstat = sig;
@@ -2410,6 +2412,7 @@ ptracestop(struct thread *td, int sig)
 	struct proc *p = td->td_proc;
 
 	PROC_LOCK_ASSERT(p, MA_OWNED);
+	KASSERT(!(p->p_flag & P_WEXIT), ("Stopping exiting process"));
 	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK,
 	    &p->p_mtx.lock_object, "Stopping for traced signal");
 
@@ -2648,7 +2651,7 @@ issignal(struct thread *td, int stop_all
 			 * process group, ignore tty stop signals.
 			 */
 			if (prop & SA_STOP) {
-				if (p->p_flag & P_TRACED ||
+				if (p->p_flag & (P_TRACED|P_WEXIT) ||
 		    		    (p->p_pgrp->pg_jobc == 0 &&
 				     prop & SA_TTYSTOP))
 					break;	/* == ignore */


More information about the svn-src-all mailing list