Commit 056ffaad authored by Linus Torvalds's avatar Linus Torvalds

Fix thread group leader zombie leak

Petr Vandrovec noticed a problem where the thread group leader
would not be properly reaped if the parent of the thread group
was ignoring SIGCHLD, and the thread group leader had exited
before the last sub-thread.

Fixed by Ingo Molnar.
parent e220fdf7
...@@ -49,9 +49,11 @@ static void __unhash_process(struct task_struct *p) ...@@ -49,9 +49,11 @@ static void __unhash_process(struct task_struct *p)
void release_task(struct task_struct * p) void release_task(struct task_struct * p)
{ {
int zap_leader;
task_t *leader; task_t *leader;
struct dentry *proc_dentry; struct dentry *proc_dentry;
repeat:
BUG_ON(p->state < TASK_ZOMBIE); BUG_ON(p->state < TASK_ZOMBIE);
atomic_dec(&p->user->processes); atomic_dec(&p->user->processes);
...@@ -70,10 +72,21 @@ void release_task(struct task_struct * p) ...@@ -70,10 +72,21 @@ void release_task(struct task_struct * p)
* group, and the leader is zombie, then notify the * group, and the leader is zombie, then notify the
* group leader's parent process. (if it wants notification.) * group leader's parent process. (if it wants notification.)
*/ */
zap_leader = 0;
leader = p->group_leader; leader = p->group_leader;
if (leader != p && thread_group_empty(leader) && if (leader != p && thread_group_empty(leader) && leader->state == TASK_ZOMBIE) {
leader->state == TASK_ZOMBIE && leader->exit_signal != -1) BUG_ON(leader->exit_signal == -1);
do_notify_parent(leader, leader->exit_signal); do_notify_parent(leader, leader->exit_signal);
/*
* If we were the last child thread and the leader has
* exited already, and the leader's parent ignores SIGCHLD,
* then we are the one who should release the leader.
*
* do_notify_parent() will have marked it self-reaping in
* that case.
*/
zap_leader = (leader->exit_signal == -1);
}
p->parent->cutime += p->utime + p->cutime; p->parent->cutime += p->utime + p->cutime;
p->parent->cstime += p->stime + p->cstime; p->parent->cstime += p->stime + p->cstime;
...@@ -88,6 +101,10 @@ void release_task(struct task_struct * p) ...@@ -88,6 +101,10 @@ void release_task(struct task_struct * p)
proc_pid_flush(proc_dentry); proc_pid_flush(proc_dentry);
release_thread(p); release_thread(p);
put_task_struct(p); put_task_struct(p);
p = leader;
if (unlikely(zap_leader))
goto repeat;
} }
/* we are using it only for SMP init */ /* we are using it only for SMP init */
......
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