__ptrace_detach: avoid task_detached(), check do_notify_parent()
__ptrace_detach() relies on the current obscure behaviour of do_notify_parent(tsk) which changes tsk->exit_signal if this child should be silently reaped. That is why we check task_detached(), it is true if the task is sub-thread, or it is the group_leader but its exit_signal was changed by do_notify_parent(). This is confusing, change the code to rely on !thread_group_leader() or the value returned by do_notify_parent(). Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Tejun Heo <tj@kernel.org>
This commit is contained in:
Родитель
45cdf5cc07
Коммит
9843a1e977
|
@ -370,25 +370,28 @@ static int ignoring_children(struct sighand_struct *sigh)
|
|||
*/
|
||||
static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
|
||||
{
|
||||
bool dead;
|
||||
|
||||
__ptrace_unlink(p);
|
||||
|
||||
if (p->exit_state == EXIT_ZOMBIE) {
|
||||
if (!task_detached(p) && thread_group_empty(p)) {
|
||||
if (p->exit_state != EXIT_ZOMBIE)
|
||||
return false;
|
||||
|
||||
dead = !thread_group_leader(p);
|
||||
|
||||
if (!dead && thread_group_empty(p)) {
|
||||
if (!same_thread_group(p->real_parent, tracer))
|
||||
do_notify_parent(p, p->exit_signal);
|
||||
dead = do_notify_parent(p, p->exit_signal);
|
||||
else if (ignoring_children(tracer->sighand)) {
|
||||
__wake_up_parent(p, tracer);
|
||||
p->exit_signal = -1;
|
||||
dead = true;
|
||||
}
|
||||
}
|
||||
if (task_detached(p)) {
|
||||
/* Mark it as in the process of being reaped. */
|
||||
if (dead)
|
||||
p->exit_state = EXIT_DEAD;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return dead;
|
||||
}
|
||||
|
||||
static int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||
|
|
Загрузка…
Ссылка в новой задаче