Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -393,10 +393,12 @@ struct filedesc *fd; struct filedesc_to_leader *fdtol; struct sigacts *newsigacts; + int has_ptrace_fork; sx_assert(&proctree_lock, SX_LOCKED); sx_assert(&allproc_lock, SX_XLOCKED); + has_ptrace_fork = 0; p1 = td->td_proc; trypid = fork_findpid(fr->fr_flags); @@ -732,6 +734,7 @@ td->td_dbgflags |= TDB_FORK; td->td_dbg_forked = p2->p_pid; td2->td_dbgflags |= TDB_STOPATFORK; + has_ptrace_fork = 1; } if (fr->fr_flags & RFPPWAIT) { td->td_pflags |= TDP_RFPPWAIT; @@ -756,7 +759,23 @@ procdesc_finit(p2->p_procdesc, fp_procdesc); fdrop(fp_procdesc, td); } - + + if( __predict_false( has_ptrace_fork ) ) + { + sx_xlock(&proctree_lock); + PROC_LOCK(p2); + if( p2->p_pptr->p_ptevents & PTRACE_FORK ) + { + if( td2->td_dbgflags & TDB_STOPATFORK ) + { + proc_set_traced(p2, true); + proc_reparent(p2, p1->p_pptr); + } + } + sx_xunlock(&proctree_lock); + PROC_UNLOCK(p2); + } + if ((fr->fr_flags & RFSTOPPED) == 0) { /* * If RFSTOPPED not requested, make child runnable and @@ -776,8 +795,6 @@ /* * Wait until debugger is attached to child. */ - while (td2->td_proc == p2 && (td2->td_dbgflags & TDB_STOPATFORK) != 0) - cv_wait(&p2->p_dbgwait, &p2->p_mtx); _PRELE(p2); racct_proc_fork_done(p2); PROC_UNLOCK(p2); @@ -1063,24 +1080,18 @@ void fork_return(struct thread *td, struct trapframe *frame) { - struct proc *p, *dbg; + struct proc *p; p = td->td_proc; if (td->td_dbgflags & TDB_STOPATFORK) { - sx_xlock(&proctree_lock); PROC_LOCK(p); - if (p->p_pptr->p_ptevents & PTRACE_FORK) { + if (p->p_flag & P_TRACED ) { /* - * If debugger still wants auto-attach for the - * parent's children, do it now. + * Inform the debugger if one is still present */ - dbg = p->p_pptr->p_pptr; - proc_set_traced(p, true); CTR2(KTR_PTRACE, "fork_return: attaching to new child pid %d: oppid %d", p->p_pid, p->p_oppid); - proc_reparent(p, dbg); - sx_xunlock(&proctree_lock); td->td_dbgflags |= TDB_CHILD | TDB_SCX | TDB_FSTP; ptracestop(td, SIGSTOP, NULL); td->td_dbgflags &= ~(TDB_CHILD | TDB_SCX); @@ -1088,9 +1099,7 @@ /* * ... otherwise clear the request. */ - sx_xunlock(&proctree_lock); td->td_dbgflags &= ~TDB_STOPATFORK; - cv_broadcast(&p->p_dbgwait); } PROC_UNLOCK(p); } else if (p->p_flag & P_TRACED || td->td_dbgflags & TDB_BORN) { Index: sys/kern/kern_proc.c =================================================================== --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -266,7 +266,6 @@ mtx_init(&p->p_itimmtx, "pitiml", NULL, MTX_SPIN | MTX_NEW); mtx_init(&p->p_profmtx, "pprofl", NULL, MTX_SPIN | MTX_NEW); cv_init(&p->p_pwait, "ppwait"); - cv_init(&p->p_dbgwait, "dbgwait"); TAILQ_INIT(&p->p_threads); /* all threads in proc */ EVENTHANDLER_DIRECT_INVOKE(process_init, p); p->p_stats = pstats_alloc(); Index: sys/kern/kern_sig.c =================================================================== --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -2581,7 +2581,6 @@ } if ((td->td_dbgflags & TDB_STOPATFORK) != 0) { td->td_dbgflags &= ~TDB_STOPATFORK; - cv_broadcast(&p->p_dbgwait); } stopme: thread_suspend_switch(td, p); Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h +++ sys/sys/proc.h @@ -685,8 +685,6 @@ LIST_HEAD(, mqueue_notifier) p_mqnotifier; /* (c) mqueue notifiers.*/ struct kdtrace_proc *p_dtrace; /* (*) DTrace-specific data. */ struct cv p_pwait; /* (*) wait cv for exit/exec. */ - struct cv p_dbgwait; /* (*) wait cv for debugger attach - after fork. */ uint64_t p_prev_runtime; /* (c) Resource usage accounting. */ struct racct *p_racct; /* (b) Resource accounting. */ int p_throttled; /* (c) Flag for racct pcpu throttling */