Date: Mon, 27 Feb 2012 21:10:11 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r232240 - in head/sys: kern sys Message-ID: <201202272110.q1RLABjb037139@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Mon Feb 27 21:10:10 2012 New Revision: 232240 URL: http://svn.freebsd.org/changeset/base/232240 Log: 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 Modified: head/sys/kern/kern_fork.c head/sys/kern/subr_syscall.c head/sys/sys/proc.h Modified: head/sys/kern/kern_fork.c ============================================================================== --- head/sys/kern/kern_fork.c Mon Feb 27 20:52:20 2012 (r232239) +++ head/sys/kern/kern_fork.c Mon Feb 27 21:10:10 2012 (r232240) @@ -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: head/sys/kern/subr_syscall.c ============================================================================== --- head/sys/kern/subr_syscall.c Mon Feb 27 20:52:20 2012 (r232239) +++ head/sys/kern/subr_syscall.c Mon Feb 27 21:10:10 2012 (r232240) @@ -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: head/sys/sys/proc.h ============================================================================== --- head/sys/sys/proc.h Mon Feb 27 20:52:20 2012 (r232239) +++ head/sys/sys/proc.h Mon Feb 27 21:10:10 2012 (r232240) @@ -311,6 +311,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 *); @@ -415,6 +416,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.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201202272110.q1RLABjb037139>