diff options
author | jhb <jhb@FreeBSD.org> | 2001-03-07 02:22:31 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-03-07 02:22:31 +0000 |
commit | fc1cdb0ea4595a57bb61542f9cd485e395f645d2 (patch) | |
tree | 3b9dc634866e173b62336910f2e995868c8bfad8 /sys/kern/kern_exit.c | |
parent | e2c9c435ffe8047a6d98aa3ad6a1c783ecedc9e9 (diff) | |
download | FreeBSD-src-fc1cdb0ea4595a57bb61542f9cd485e395f645d2.zip FreeBSD-src-fc1cdb0ea4595a57bb61542f9cd485e395f645d2.tar.gz |
- Call proc_reparent() when handing a process off to init in exit rather
than dinking around in the process lists explicitly.
- Hold both the proctree lock and proc lock of the child process when
reparenting a process via proc_reparent.
- Lock processes while sending them signals.
- Miscellaenous proc locking.
- proc_reparent() now asserts that the child is locked in addition to an
exclusive proctree lock.
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r-- | sys/kern/kern_exit.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 81cbdb9..7ddf7f0 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -291,10 +291,8 @@ exit1(p, rv) wakeup((caddr_t) initproc); for (; q != NULL; q = nq) { nq = LIST_NEXT(q, p_sibling); - LIST_REMOVE(q, p_sibling); - LIST_INSERT_HEAD(&initproc->p_children, q, p_sibling); - q->p_pptr = initproc; PROC_LOCK(q); + proc_reparent(q, initproc); q->p_sigparent = SIGCHLD; /* * Traced processes are killed @@ -302,10 +300,9 @@ exit1(p, rv) */ if (q->p_flag & P_TRACED) { q->p_flag &= ~P_TRACED; - PROC_UNLOCK(q); psignal(q, SIGKILL); - } else - PROC_UNLOCK(q); + } + PROC_UNLOCK(q); } /* @@ -335,7 +332,6 @@ exit1(p, rv) */ PROC_LOCK(p); KNOTE(&p->p_klist, NOTE_EXIT); - PROC_UNLOCK(p); /* * Notify parent that we're gone. If parent has the PS_NOCLDWAIT @@ -354,13 +350,15 @@ exit1(p, rv) wakeup((caddr_t)pp); } - if (p->p_sigparent && p->p_pptr != initproc) { + PROC_LOCK(p->p_pptr); + if (p->p_sigparent && p->p_pptr != initproc) psignal(p->p_pptr, p->p_sigparent); - } else { + else psignal(p->p_pptr, SIGCHLD); - } - + PROC_UNLOCK(p->p_pptr); + PROC_UNLOCK(p); PROCTREE_LOCK(PT_RELEASE); + /* * Clear curproc after we've done all operations * that could block, and before tearing down the rest @@ -461,16 +459,16 @@ loop: nfound++; mtx_lock_spin(&sched_lock); if (p->p_stat == SZOMB) { - mtx_unlock_spin(&sched_lock); - PROC_UNLOCK(p); - PROCTREE_LOCK(PT_RELEASE); - /* charge childs scheduling cpu usage to parent */ if (curproc->p_pid != 1) { curproc->p_estcpu = ESTCPULIM(curproc->p_estcpu + p->p_estcpu); } + mtx_unlock_spin(&sched_lock); + PROC_UNLOCK(p); + PROCTREE_LOCK(PT_RELEASE); + q->p_retval[0] = p->p_pid; #ifdef COMPAT_43 if (compat) @@ -490,19 +488,25 @@ loop: * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. */ + PROCTREE_LOCK(PT_EXCLUSIVE); if (p->p_oppid) { - PROCTREE_LOCK(PT_EXCLUSIVE); if ((t = pfind(p->p_oppid)) != NULL) { + PROC_LOCK(p); p->p_oppid = 0; proc_reparent(p, t); + PROC_UNLOCK(p); + PROC_LOCK(t); psignal(t, SIGCHLD); - wakeup((caddr_t)t); + PROC_UNLOCK(t); PROCTREE_LOCK(PT_RELEASE); + wakeup((caddr_t)t); return (0); } - PROCTREE_LOCK(PT_RELEASE); } + PROCTREE_LOCK(PT_RELEASE); + PROC_LOCK(p); p->p_xstat = 0; + PROC_UNLOCK(p); ruadd(&q->p_stats->p_cru, p->p_ru); FREE(p->p_ru, M_ZOMBIE); p->p_ru = NULL; @@ -617,6 +621,7 @@ proc_reparent(child, parent) { PROCTREE_ASSERT(PT_EXCLUSIVE); + PROC_LOCK_ASSERT(child, MA_OWNED); if (child->p_pptr == parent) return; |