diff options
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r-- | sys/kern/kern_exit.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index d4ed909..8846ae4 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -857,13 +857,13 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options) PROC_LOCK(q); sigqueue_take(p->p_ksi); PROC_UNLOCK(q); - PROC_UNLOCK(p); /* * If we got the child via a ptrace 'attach', we need to give it back * to the old parent. */ - if (p->p_oppid != 0) { + if (p->p_oppid != 0 && p->p_oppid != p->p_pptr->p_pid) { + PROC_UNLOCK(p); t = proc_realparent(p); PROC_LOCK(t); PROC_LOCK(p); @@ -880,6 +880,8 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options) sx_xunlock(&proctree_lock); return; } + p->p_oppid = 0; + PROC_UNLOCK(p); /* * Remove other references to this process to ensure we have an @@ -962,7 +964,8 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options) static int proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, - int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo) + int *status, int options, struct __wrusage *wrusage, siginfo_t *siginfo, + int check_only) { struct rusage *rup; @@ -1098,7 +1101,7 @@ proc_to_reap(struct thread *td, struct proc *p, idtype_t idtype, id_t id, calccru(p, &rup->ru_utime, &rup->ru_stime); } - if (p->p_state == PRS_ZOMBIE) { + if (p->p_state == PRS_ZOMBIE && !check_only) { proc_reap(td, p, status, options); return (-1); } @@ -1192,7 +1195,7 @@ loop: sx_xlock(&proctree_lock); LIST_FOREACH(p, &q->p_children, p_sibling) { ret = proc_to_reap(td, p, idtype, id, status, options, - wrusage, siginfo); + wrusage, siginfo, 0); if (ret == 0) continue; else if (ret == 1) @@ -1294,15 +1297,17 @@ loop: * for. By maintaining a list of orphans we allow the parent * to successfully wait until the child becomes a zombie. */ - LIST_FOREACH(p, &q->p_orphans, p_orphan) { - ret = proc_to_reap(td, p, idtype, id, status, options, - wrusage, siginfo); - if (ret == 0) - continue; - else if (ret == 1) - nfound++; - else - return (0); + if (nfound == 0) { + LIST_FOREACH(p, &q->p_orphans, p_orphan) { + ret = proc_to_reap(td, p, idtype, id, NULL, options, + NULL, NULL, 1); + if (ret != 0) { + KASSERT(ret != -1, ("reaped an orphan (pid %d)", + (int)td->td_retval[0])); + nfound++; + break; + } + } } if (nfound == 0) { sx_xunlock(&proctree_lock); |