FreeBSD/sys/kern/kern_fork.c
/*
 * Simplified back end of syscall(), used when returning from fork()
 * directly into user mode.  This function is passed in to fork_exit()
 * as the first parameter and is called when returning to a new
 * userland process.
 */
Simplified back end of syscall(), used when returning from fork()
directly into user mode.  This function is passed in to fork_exit()
as the first parameter and is called when returning to a new
userland process.
Simplified back end of syscall () used when returning from fork () directly into user mode . This function is passed in to fork_exit () as the first parameter and is called when returning to a new userland process .
void
fork_return(struct thread *td, struct trapframe *frame)
{
	struct proc *p, *dbg;
	p = td->td_proc;
	if (td->td_dbgflags & TDB_STOPATFORK) {
		sx_xlock(&proctree_lock);
		PROC_LOCK(p);
		if ((p->p_pptr->p_flag & (P_TRACED | P_FOLLOWFORK)) ==
		    (P_TRACED | P_FOLLOWFORK)) {
			dbg = p->p_pptr->p_pptr;
			p->p_flag |= P_TRACED;
			p->p_oppid = p->p_pptr->p_pid;
			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;
			ptracestop(td, SIGSTOP);
			td->td_dbgflags &= ~(TDB_CHILD | TDB_SCX);
		} else {
			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) {
		PROC_LOCK(p);
		td->td_dbgflags |= TDB_SCX;
		_STOPEVENT(p, S_SCX, td->td_dbg_sc_code);
		if ((p->p_stops & S_PT_SCX) != 0 ||
		    (td->td_dbgflags & TDB_BORN) != 0)
			ptracestop(td, SIGTRAP);
		td->td_dbgflags &= ~(TDB_SCX | TDB_BORN);
		PROC_UNLOCK(p);
	}
	userret(td, frame);
#ifdef KTRACE
	if (KTRPOINT(td, KTR_SYSRET))
		ktrsysret(SYS_fork, 0, 0);
#endif
}
void fork_return ( struct thread * td , struct trapframe * frame ) { struct proc * p , * dbg ; p = td -> td_proc ; if ( td -> td_dbgflags & TDB_STOPATFORK ) { sx_xlock ( & proctree_lock ) ; PROC_LOCK ( p ) ; if ( ( p -> p_pptr -> p_flag & ( P_TRACED | P_FOLLOWFORK ) ) == ( P_TRACED | P_FOLLOWFORK ) ) { dbg = p -> p_pptr -> p_pptr ; p -> p_flag |= P_TRACED ; p -> p_oppid = p -> p_pptr -> p_pid ; CTR2 ( KTR_PTRACE , " " , p -> p_pid , p -> p_oppid ) ; proc_reparent ( p , dbg ) ; sx_xunlock ( & proctree_lock ) ; td -> td_dbgflags |= TDB_CHILD | TDB_SCX ; ptracestop ( td , SIGSTOP ) ; td -> td_dbgflags &= ~ ( TDB_CHILD | TDB_SCX ) ; } else { 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 ) { PROC_LOCK ( p ) ; td -> td_dbgflags |= TDB_SCX ; _STOPEVENT ( p , S_SCX , td -> td_dbg_sc_code ) ; if ( ( p -> p_stops & S_PT_SCX ) != 0 || ( td -> td_dbgflags & TDB_BORN ) != 0 ) ptracestop ( td , SIGTRAP ) ; td -> td_dbgflags &= ~ ( TDB_SCX | TDB_BORN ) ; PROC_UNLOCK ( p ) ; } userret ( td , frame ) ; #ifdef KTRACE if ( KTRPOINT ( td , KTR_SYSRET ) ) ktrsysret ( SYS_fork , 0 , 0 ) ; #endif }
Simplified back end of syscall(), used when returning from fork()
 directly into user mode.
Simplified back end of syscall () used when returning from fork () directly into user mode .
/*
			 * If debugger still wants auto-attach for the
			 * parent's children, do it now.
			 */ /*
			 * ... otherwise clear the request.
			 */ /*
		 * This is the start of a new thread in a traced
		 * process.  Report a system call exit event.
		 */