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