svn commit: r302999 - head/sys/kern

Konstantin Belousov kib at FreeBSD.org
Mon Jul 18 10:53:49 UTC 2016


Author: kib
Date: Mon Jul 18 10:53:47 2016
New Revision: 302999
URL: https://svnweb.freebsd.org/changeset/base/302999

Log:
  The assertion re-added in r302614 was triggered when stopping signal
  is delivered to vforked child.  Issue is that we avoid stopping such
  children in issignal() to not block parents.  But executed AST, which
  ignored stops, leaves the child with the signal pending but no AST
  pending.
  
  On first exec after vfork(), call signotify() to handle pending
  reenabled signals.  Adjust the assert to not check vfork children
  until exec.
  
  Reported and tested by:	pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	2 weeks

Modified:
  head/sys/kern/kern_exec.c
  head/sys/kern/subr_trap.c

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c	Mon Jul 18 09:29:08 2016	(r302998)
+++ head/sys/kern/kern_exec.c	Mon Jul 18 10:53:47 2016	(r302999)
@@ -760,6 +760,8 @@ interpret:
 	if (p->p_flag & P_PPWAIT) {
 		p->p_flag &= ~(P_PPWAIT | P_PPTRACE);
 		cv_broadcast(&p->p_pwait);
+		/* STOPs are no longer ignored, arrange for AST */
+		signotify(td);
 	}
 
 	/*

Modified: head/sys/kern/subr_trap.c
==============================================================================
--- head/sys/kern/subr_trap.c	Mon Jul 18 09:29:08 2016	(r302998)
+++ head/sys/kern/subr_trap.c	Mon Jul 18 10:53:47 2016	(r302999)
@@ -107,15 +107,20 @@ userret(struct thread *td, struct trapfr
 	 * multi-threaded processes, where signal distribution might
 	 * change due to other threads changing sigmask, the check is
 	 * racy and cannot be performed reliably.
+	 * If current process is vfork child, indicated by P_PPWAIT, then
+	 * issignal() ignores stops, so we block the check to avoid
+	 * classifying pending signals.
 	 */
 	if (p->p_numthreads == 1) {
 		PROC_LOCK(p);
 		thread_lock(td);
-		KASSERT(!SIGPENDING(td) ||
-		    (td->td_flags & (TDF_NEEDSIGCHK | TDF_ASTPENDING)) ==
-		    (TDF_NEEDSIGCHK | TDF_ASTPENDING),
-		    ("failed to set signal flags for ast p %p td %p fl %x",
-		    p, td, td->td_flags));
+		if ((p->p_flag & P_PPWAIT) == 0) {
+			KASSERT(!SIGPENDING(td) || (td->td_flags &
+			    (TDF_NEEDSIGCHK | TDF_ASTPENDING)) ==
+			    (TDF_NEEDSIGCHK | TDF_ASTPENDING),
+			    ("failed to set signal flags for ast p %p "
+			    "td %p fl %x", p, td, td->td_flags));
+		}
 		thread_unlock(td);
 		PROC_UNLOCK(p);
 	}
@@ -281,12 +286,15 @@ ast(struct trapframe *framep)
 		 * td_flags, since signal might have been delivered
 		 * after we cleared td_flags above.  This is one of
 		 * the reason for looping check for AST condition.
+		 * See comment in userret() about P_PPWAIT.
 		 */
-		KASSERT(!SIGPENDING(td) ||
-		    (td->td_flags & (TDF_NEEDSIGCHK | TDF_ASTPENDING)) ==
-		    (TDF_NEEDSIGCHK | TDF_ASTPENDING),
-		    ("failed2 to set signal flags for ast p %p td %p fl %x %x",
-		    p, td, flags, td->td_flags));
+		if ((p->p_flag & P_PPWAIT) == 0) {
+			KASSERT(!SIGPENDING(td) || (td->td_flags &
+			    (TDF_NEEDSIGCHK | TDF_ASTPENDING)) ==
+			    (TDF_NEEDSIGCHK | TDF_ASTPENDING),
+			    ("failed2 to set signal flags for ast p %p td %p "
+			    "fl %x %x", p, td, flags, td->td_flags));
+		}
 		thread_unlock(td);
 		PROC_UNLOCK(p);
 	}


More information about the svn-src-head mailing list