__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:
parent
45cdf5cc07
commit
9843a1e977
1 changed files with 18 additions and 15 deletions
|
@ -370,25 +370,28 @@ static int ignoring_children(struct sighand_struct *sigh)
|
||||||
*/
|
*/
|
||||||
static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
|
static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
|
||||||
{
|
{
|
||||||
|
bool dead;
|
||||||
|
|
||||||
__ptrace_unlink(p);
|
__ptrace_unlink(p);
|
||||||
|
|
||||||
if (p->exit_state == EXIT_ZOMBIE) {
|
if (p->exit_state != EXIT_ZOMBIE)
|
||||||
if (!task_detached(p) && thread_group_empty(p)) {
|
return false;
|
||||||
if (!same_thread_group(p->real_parent, tracer))
|
|
||||||
do_notify_parent(p, p->exit_signal);
|
dead = !thread_group_leader(p);
|
||||||
else if (ignoring_children(tracer->sighand)) {
|
|
||||||
__wake_up_parent(p, tracer);
|
if (!dead && thread_group_empty(p)) {
|
||||||
p->exit_signal = -1;
|
if (!same_thread_group(p->real_parent, tracer))
|
||||||
}
|
dead = do_notify_parent(p, p->exit_signal);
|
||||||
}
|
else if (ignoring_children(tracer->sighand)) {
|
||||||
if (task_detached(p)) {
|
__wake_up_parent(p, tracer);
|
||||||
/* Mark it as in the process of being reaped. */
|
p->exit_signal = -1;
|
||||||
p->exit_state = EXIT_DEAD;
|
dead = true;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Mark it as in the process of being reaped. */
|
||||||
return false;
|
if (dead)
|
||||||
|
p->exit_state = EXIT_DEAD;
|
||||||
|
return dead;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ptrace_detach(struct task_struct *child, unsigned int data)
|
static int ptrace_detach(struct task_struct *child, unsigned int data)
|
||||||
|
|
Loading…
Reference in a new issue