svn commit: r232864 - in stable/9/sys: kern sys

Konstantin Belousov kib at FreeBSD.org
Mon Mar 12 12:53:28 UTC 2012


Author: kib
Date: Mon Mar 12 12:53:27 2012
New Revision: 232864
URL: http://svn.freebsd.org/changeset/base/232864

Log:
  MFC r232240:
  Currently, the debugger attached to the process executing vfork() does
  not get syscall exit notification until the child performed exec of
  exit.  Swap the order of doing ptracestop() and waiting for P_PPWAIT
  clearing, by postponing the wait into syscallret after ptracestop()
  notification is done.

Modified:
  stable/9/sys/kern/kern_fork.c
  stable/9/sys/kern/subr_syscall.c
  stable/9/sys/sys/proc.h
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/kern/kern_fork.c
==============================================================================
--- stable/9/sys/kern/kern_fork.c	Mon Mar 12 12:29:31 2012	(r232863)
+++ stable/9/sys/kern/kern_fork.c	Mon Mar 12 12:53:27 2012	(r232864)
@@ -708,6 +708,10 @@ do_fork(struct thread *td, int flags, st
 		_PHOLD(p2);
 		p2_held = 1;
 	}
+	if (flags & RFPPWAIT) {
+		td->td_pflags |= TDP_RFPPWAIT;
+		td->td_rfppwait_p = p2;
+	}
 	PROC_UNLOCK(p2);
 	if ((flags & RFSTOPPED) == 0) {
 		/*
@@ -740,14 +744,6 @@ do_fork(struct thread *td, int flags, st
 		cv_wait(&p2->p_dbgwait, &p2->p_mtx);
 	if (p2_held)
 		_PRELE(p2);
-
-	/*
-	 * Preserve synchronization semantics of vfork.  If waiting for
-	 * child to exec or exit, set P_PPWAIT on child, and sleep on our
-	 * proc (in case of exit).
-	 */
-	while (p2->p_flag & P_PPWAIT)
-		cv_wait(&p2->p_pwait, &p2->p_mtx);
 	PROC_UNLOCK(p2);
 }
 

Modified: stable/9/sys/kern/subr_syscall.c
==============================================================================
--- stable/9/sys/kern/subr_syscall.c	Mon Mar 12 12:29:31 2012	(r232863)
+++ stable/9/sys/kern/subr_syscall.c	Mon Mar 12 12:53:27 2012	(r232864)
@@ -165,7 +165,7 @@ syscallenter(struct thread *td, struct s
 static inline void
 syscallret(struct thread *td, int error, struct syscall_args *sa __unused)
 {
-	struct proc *p;
+	struct proc *p, *p2;
 	int traced;
 
 	p = td->td_proc;
@@ -223,4 +223,23 @@ syscallret(struct thread *td, int error,
 		td->td_dbgflags &= ~(TDB_SCX | TDB_EXEC | TDB_FORK);
 		PROC_UNLOCK(p);
 	}
+
+	if (td->td_pflags & TDP_RFPPWAIT) {
+		/*
+		 * Preserve synchronization semantics of vfork.  If
+		 * waiting for child to exec or exit, fork set
+		 * P_PPWAIT on child, and there we sleep on our proc
+		 * (in case of exit).
+		 *
+		 * Do it after the ptracestop() above is finished, to
+		 * not block our debugger until child execs or exits
+		 * to finish vfork wait.
+		 */
+		td->td_pflags &= ~TDP_RFPPWAIT;
+		p2 = td->td_rfppwait_p;
+		PROC_LOCK(p2);
+		while (p2->p_flag & P_PPWAIT)
+			cv_wait(&p2->p_pwait, &p2->p_mtx);
+		PROC_UNLOCK(p2);
+	}
 }

Modified: stable/9/sys/sys/proc.h
==============================================================================
--- stable/9/sys/sys/proc.h	Mon Mar 12 12:29:31 2012	(r232863)
+++ stable/9/sys/sys/proc.h	Mon Mar 12 12:53:27 2012	(r232864)
@@ -310,6 +310,7 @@ struct thread {
 	struct vnet	*td_vnet;	/* (k) Effective vnet. */
 	const char	*td_vnet_lpush;	/* (k) Debugging vnet push / pop. */
 	struct trapframe *td_intr_frame;/* (k) Frame of the current irq */
+	struct proc *td_rfppwait_p;	/* (k) The vforked child */
 };
 
 struct mtx *thread_lock_block(struct thread *);
@@ -414,6 +415,7 @@ do {									\
 #define	TDP_CALLCHAIN	0x00400000 /* Capture thread's callchain */
 #define	TDP_IGNSUSP	0x00800000 /* Permission to ignore the MNTK_SUSPEND* */
 #define	TDP_AUDITREC	0x01000000 /* Audit record pending on thread */
+#define	TDP_RFPPWAIT	0x02000000 /* Handle RFPPWAIT on syscall exit */
 
 /*
  * Reasons that the current thread can not be run yet.


More information about the svn-src-stable-9 mailing list