summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_syscall.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-02-27 21:10:10 +0000
committerkib <kib@FreeBSD.org>2012-02-27 21:10:10 +0000
commit0c3998cc9e3ca0b91b97214b281c4549287bcca7 (patch)
tree288af65037796dba1ccb410821163bb5b70f55f7 /sys/kern/subr_syscall.c
parent57e2f851ed8c3cd5f35ee1d8ab0edc357c7137f1 (diff)
downloadFreeBSD-src-0c3998cc9e3ca0b91b97214b281c4549287bcca7.zip
FreeBSD-src-0c3998cc9e3ca0b91b97214b281c4549287bcca7.tar.gz
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. Reported, tested and reviewed by: Dmitry Mikulin <dmitrym juniper net> MFC after: 2 weeks
Diffstat (limited to 'sys/kern/subr_syscall.c')
-rw-r--r--sys/kern/subr_syscall.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index 9c4dd48..367ea67 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -165,7 +165,7 @@ syscallenter(struct thread *td, struct syscall_args *sa)
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, struct syscall_args *sa __unused)
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);
+ }
}
OpenPOWER on IntegriCloud