Index: sys/kern/kern_exit.c =================================================================== --- sys/kern/kern_exit.c (revision 230617) +++ sys/kern/kern_exit.c (working copy) @@ -680,7 +680,7 @@ */ void proc_reap(struct thread *td, struct proc *p, int *status, int options, - struct rusage *rusage) + struct rusage *rusage, int child) { struct proc *q, *t; @@ -720,7 +720,6 @@ if (p->p_oppid && (t = pfind(p->p_oppid)) != NULL) { PROC_LOCK(p); proc_reparent(p, t); - p->p_pptr->p_dbg_child--; p->p_oppid = 0; PROC_UNLOCK(p); pksignal(t, SIGCHLD, p->p_ksi); @@ -738,7 +737,10 @@ sx_xlock(&allproc_lock); LIST_REMOVE(p, p_list); /* off zombproc */ sx_xunlock(&allproc_lock); - LIST_REMOVE(p, p_sibling); + if (child) + LIST_REMOVE(p, p_sibling); + else + LIST_REMOVE(p, p_orphan); leavepgrp(p); #ifdef PROCDESC if (p->p_procdesc != NULL) @@ -859,7 +861,7 @@ nfound++; PROC_SLOCK(p); if (p->p_state == PRS_ZOMBIE) { - proc_reap(td, p, status, options, rusage); + proc_reap(td, p, status, options, rusage, 1); return (0); } if ((p->p_flag & P_STOPPED_SIG) && @@ -893,16 +895,47 @@ if (status) *status = SIGCONT; + } + PROC_UNLOCK(p); + } + LIST_FOREACH(p, &q->p_orphans, p_orphan) { + PROC_LOCK(p); + if (pid != WAIT_ANY && + p->p_pid != pid && p->p_pgid != -pid) { + PROC_UNLOCK(p); + continue; + } + if (p_canwait(td, p)) { + PROC_UNLOCK(p); + continue; + } + + /* + * This special case handles a kthread spawned by linux_clone + * (see linux_misc.c). The linux_wait4 and linux_waitpid + * functions need to be able to distinguish between waiting + * on a process and waiting on a thread. It is a thread if + * p_sigparent is not SIGCHLD, and the WLINUXCLONE option + * signifies we want to wait for threads and not processes. + */ + if ((p->p_sigparent != SIGCHLD) ^ + ((options & WLINUXCLONE) != 0)) { + PROC_UNLOCK(p); + continue; + } + + nfound++; + PROC_SLOCK(p); + if (p->p_state == PRS_ZOMBIE) { + proc_reap(td, p, status, options, rusage, 0); return (0); } + PROC_SUNLOCK(p); PROC_UNLOCK(p); } if (nfound == 0) { sx_xunlock(&proctree_lock); - if (td->td_proc->p_dbg_child) - return (0); - else - return (ECHILD); + return (ECHILD); } if (options & WNOHANG) { sx_xunlock(&proctree_lock); @@ -929,6 +962,7 @@ void proc_reparent(struct proc *child, struct proc *parent) { + struct proc *p; sx_assert(&proctree_lock, SX_XLOCKED); PROC_LOCK_ASSERT(child, MA_OWNED); @@ -940,5 +974,17 @@ PROC_UNLOCK(child->p_pptr); LIST_REMOVE(child, p_sibling); LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); + + LIST_FOREACH(p, &parent->p_orphans, p_orphan) { + if (p == child) { + LIST_REMOVE(child, p_orphan); + break; + } + } + if (child->p_flag & P_TRACED) { + LIST_INSERT_HEAD(&child->p_pptr->p_orphans, child, p_orphan); + PROC_UNLOCK(child); + PROC_LOCK(child); + } child->p_pptr = parent; } Index: sys/kern/kern_fork.c =================================================================== --- sys/kern/kern_fork.c (revision 230617) +++ sys/kern/kern_fork.c (working copy) @@ -590,6 +590,7 @@ LIST_INSERT_AFTER(p1, p2, p_pglist); PGRP_UNLOCK(p1->p_pgrp); LIST_INIT(&p2->p_children); + LIST_INIT(&p2->p_orphans); callout_init(&p2->p_itcallout, CALLOUT_MPSAFE); Index: sys/kern/sys_process.c =================================================================== --- sys/kern/sys_process.c (revision 230617) +++ sys/kern/sys_process.c (working copy) @@ -841,8 +841,6 @@ p->p_flag |= P_TRACED; p->p_oppid = p->p_pptr->p_pid; if (p->p_pptr != td->td_proc) { - /* Remember that a child is being debugged(traced). */ - p->p_pptr->p_dbg_child++; proc_reparent(p, td->td_proc); } data = SIGSTOP; @@ -931,7 +929,6 @@ PROC_UNLOCK(pp); PROC_LOCK(p); proc_reparent(p, pp); - p->p_pptr->p_dbg_child--; if (pp == initproc) p->p_sigparent = SIGCHLD; } Index: sys/kern/sys_procdesc.c =================================================================== --- sys/kern/sys_procdesc.c (revision 230617) +++ sys/kern/sys_procdesc.c (working copy) @@ -367,7 +367,7 @@ * procdesc_reap(). */ PROC_SLOCK(p); - proc_reap(curthread, p, NULL, 0, NULL); + proc_reap(curthread, p, NULL, 0, NULL, 0); } else { /* * If the process is not yet dead, we need to kill it, but we Index: sys/sys/proc.h =================================================================== --- sys/sys/proc.h (revision 230617) +++ sys/sys/proc.h (working copy) @@ -505,8 +505,6 @@ /* The following fields are all zeroed upon creation in fork. */ #define p_startzero p_oppid pid_t p_oppid; /* (c + e) Save ppid in ptrace. XXX */ - int p_dbg_child; /* (c + e) # of debugged children in - ptrace. */ struct vmspace *p_vmspace; /* (b) Address space. */ u_int p_swtick; /* (c) Tick when swapped in or out. */ struct itimerval p_realtimer; /* (c) Alarm timer. */ @@ -574,6 +572,8 @@ after fork. */ uint64_t p_prev_runtime; /* (c) Resource usage accounting. */ struct racct *p_racct; /* (b) Resource accounting. */ + LIST_ENTRY(proc) p_orphan; /* (e) List of orphan processes. */ + LIST_HEAD(, proc) p_orphans; /* (e) Pointer to list of orphans. */ }; #define p_session p_pgrp->pg_session @@ -865,7 +865,7 @@ void proc_linkup0(struct proc *p, struct thread *td); void proc_linkup(struct proc *p, struct thread *td); void proc_reap(struct thread *td, struct proc *p, int *status, int options, - struct rusage *rusage); + struct rusage *rusage, int child); void proc_reparent(struct proc *child, struct proc *newparent); struct pstats *pstats_alloc(void); void pstats_fork(struct pstats *src, struct pstats *dst);