Commit 4e7e3674 authored by Linus Torvalds's avatar Linus Torvalds

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.
parent e66368b9
...@@ -594,6 +594,7 @@ static inline void forget_original_parent(struct task_struct * father) ...@@ -594,6 +594,7 @@ static inline void forget_original_parent(struct task_struct * father)
*/ */
static void exit_notify(struct task_struct *tsk) static void exit_notify(struct task_struct *tsk)
{ {
int state;
struct task_struct *t; struct task_struct *t;
if (signal_pending(tsk) && !tsk->signal->group_exit if (signal_pending(tsk) && !tsk->signal->group_exit
...@@ -687,8 +688,12 @@ static void exit_notify(struct task_struct *tsk) ...@@ -687,8 +688,12 @@ static void exit_notify(struct task_struct *tsk)
do_notify_parent(tsk, SIGCHLD); 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; tsk->flags |= PF_DEAD;
/* /*
* In the preemption case it must be impossible for the task * In the preemption case it must be impossible for the task
* to get runnable again, so use "_raw_" unlock to keep * to get runnable again, so use "_raw_" unlock to keep
...@@ -703,6 +708,11 @@ static void exit_notify(struct task_struct *tsk) ...@@ -703,6 +708,11 @@ static void exit_notify(struct task_struct *tsk)
*/ */
_raw_write_unlock(&tasklist_lock); _raw_write_unlock(&tasklist_lock);
local_irq_enable(); 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) NORET_TYPE void do_exit(long code)
...@@ -751,10 +761,6 @@ NORET_TYPE void do_exit(long code) ...@@ -751,10 +761,6 @@ NORET_TYPE void do_exit(long code)
tsk->exit_code = code; tsk->exit_code = code;
exit_notify(tsk); exit_notify(tsk);
if (tsk->exit_signal == -1 && tsk->ptrace == 0)
release_task(tsk);
schedule(); schedule();
BUG(); BUG();
/* Avoid "noreturn function does return". */ /* Avoid "noreturn function does return". */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment