Skip to content

Commit

Permalink
ptrace: reintroduce __ptrace_detach() as a callee of ptrace_exit()
Browse files Browse the repository at this point in the history
No functional changes, preparation for the next patch.

Move the "should we release this child" logic into the separate handler,
__ptrace_detach().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Cc: Jerome Marchand <jmarchan@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
oleg-nesterov authored and torvalds committed Apr 3, 2009
1 parent 6d69cb8 commit b1b4c67
Showing 1 changed file with 33 additions and 29 deletions.
62 changes: 33 additions & 29 deletions kernel/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,38 @@ static int ignoring_children(struct sighand_struct *sigh)
return ret;
}

/* Returns nonzero if the tracee should be released. */
int __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
{
__ptrace_unlink(p);

if (p->exit_state != EXIT_ZOMBIE)
return 0;
/*
* If it's a zombie, our attachedness prevented normal
* parent notification or self-reaping. Do notification
* now if it would have happened earlier. If it should
* reap itself we return true.
*
* If it's our own child, there is no notification to do.
* But if our normal children self-reap, then this child
* was prevented by ptrace and we must reap it now.
*/
if (!task_detached(p) && thread_group_empty(p)) {
if (!same_thread_group(p->real_parent, tracer))
do_notify_parent(p, p->exit_signal);
else if (ignoring_children(tracer->sighand))
p->exit_signal = -1;
}

if (!task_detached(p))
return 0;

/* Mark it as in the process of being reaped. */
p->exit_state = EXIT_DEAD;
return 1;
}

/*
* Detach all tasks we were using ptrace on.
* Any that need to be release_task'd are put on the @dead list.
Expand All @@ -755,36 +787,8 @@ static void ptrace_exit(struct task_struct *parent, struct list_head *dead)
struct task_struct *p, *n;

list_for_each_entry_safe(p, n, &parent->ptraced, ptrace_entry) {
__ptrace_unlink(p);

if (p->exit_state != EXIT_ZOMBIE)
continue;

/*
* If it's a zombie, our attachedness prevented normal
* parent notification or self-reaping. Do notification
* now if it would have happened earlier. If it should
* reap itself, add it to the @dead list. We can't call
* release_task() here because we already hold tasklist_lock.
*
* If it's our own child, there is no notification to do.
* But if our normal children self-reap, then this child
* was prevented by ptrace and we must reap it now.
*/
if (!task_detached(p) && thread_group_empty(p)) {
if (!same_thread_group(p->real_parent, parent))
do_notify_parent(p, p->exit_signal);
else if (ignoring_children(parent->sighand))
p->exit_signal = -1;
}

if (task_detached(p)) {
/*
* Mark it as in the process of being reaped.
*/
p->exit_state = EXIT_DEAD;
if (__ptrace_detach(parent, p))
list_add(&p->ptrace_entry, dead);
}
}
}

Expand Down

0 comments on commit b1b4c67

Please sign in to comment.