From 4e7e36746cd22aeaedc183782563502116729131 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 26 Oct 2003 19:50:03 -0800 Subject: Fix ZOMBIE race with self-reaping threads. exit_notify() used to leave a window open when a thread died that made the thread visible as a ZOMBIE even though the thread reaped itself. This closes that window by marking the thread DEAD within the tasklist_lock. --- kernel/exit.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'kernel/exit.c') diff --git a/kernel/exit.c b/kernel/exit.c index 32f739f782d1..202d7eaf3245 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -594,6 +594,7 @@ static inline void forget_original_parent(struct task_struct * father) */ static void exit_notify(struct task_struct *tsk) { + int state; struct task_struct *t; if (signal_pending(tsk) && !tsk->signal->group_exit @@ -687,8 +688,12 @@ static void exit_notify(struct task_struct *tsk) do_notify_parent(tsk, SIGCHLD); } - tsk->state = TASK_ZOMBIE; + state = TASK_ZOMBIE; + if (tsk->exit_signal == -1 && tsk->ptrace == 0) + state = TASK_DEAD; + tsk->state = state; tsk->flags |= PF_DEAD; + /* * In the preemption case it must be impossible for the task * to get runnable again, so use "_raw_" unlock to keep @@ -703,6 +708,11 @@ static void exit_notify(struct task_struct *tsk) */ _raw_write_unlock(&tasklist_lock); local_irq_enable(); + + /* If the process is dead, release it - nobody will wait for it */ + if (state == TASK_DEAD) + release_task(tsk); + } NORET_TYPE void do_exit(long code) @@ -751,10 +761,6 @@ NORET_TYPE void do_exit(long code) tsk->exit_code = code; exit_notify(tsk); - - if (tsk->exit_signal == -1 && tsk->ptrace == 0) - release_task(tsk); - schedule(); BUG(); /* Avoid "noreturn function does return". */ -- cgit v1.2.3