MFC: Close a race where the last thread in a process could be harvested via

wait() before it has finished dying.

Approved by:	re (kensmith)
MFC after:	1 week
This commit is contained in:
jhb 2005-08-05 19:02:56 +00:00
parent 8387d66d00
commit 2654179517

View File

@ -495,18 +495,16 @@ retry:
* We have to wait until after acquiring all locks before
* changing p_state. We need to avoid all possible context
* switches (including ones from blocking on a mutex) while
* marked as a zombie.
* marked as a zombie. We also have to set the zombie state
* before we release the parent process' proc lock to avoid
* a lost wakeup. So, we first call wakeup, then we grab the
* sched lock, update the state, and release the parent process'
* proc lock.
*/
wakeup(p->p_pptr);
mtx_lock_spin(&sched_lock);
p->p_state = PRS_ZOMBIE;
critical_enter();
mtx_unlock_spin(&sched_lock);
wakeup(p->p_pptr);
PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
critical_exit();
/* Do the same timestamp bookkeeping that mi_switch() would do. */
binuptime(&new_switchtime);
@ -624,6 +622,20 @@ loop:
nfound++;
if (p->p_state == PRS_ZOMBIE) {
/*
* It is possible that the last thread of this
* process is still running on another CPU
* in thread_exit() after having dropped the process
* lock via PROC_UNLOCK() but before it has completed
* cpu_throw(). In that case, the other thread must
* still hold sched_lock, so simply by acquiring
* sched_lock once we will wait long enough for the
* thread to exit in that case.
*/
mtx_lock_spin(&sched_lock);
mtx_unlock_spin(&sched_lock);
td->td_retval[0] = p->p_pid;
if (status)
*status = p->p_xstat; /* convert to int */