ptrace children revamp

ptrace no longer fiddles with the children/sibling links, and the
old ptrace_children list is gone.  Now ptrace, whether of one's own
children or another's via PTRACE_ATTACH, just uses the new ptraced
list instead.

There should be no user-visible difference that matters.  The only
change is the order in which do_wait() sees multiple stopped
children and stopped ptrace attachees.  Since wait_task_stopped()
was changed earlier so it no longer reorders the children list, we
already know this won't cause any new problems.

Signed-off-by: Roland McGrath <[email protected]>
This commit is contained in:
Roland McGrath 2008-03-24 18:36:23 -07:00
commit f470021adb
5 changed files with 160 additions and 139 deletions

View file

@ -33,13 +33,9 @@
*/
void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
{
BUG_ON(!list_empty(&child->ptrace_list));
if (child->parent == new_parent)
return;
list_add(&child->ptrace_list, &child->parent->ptrace_children);
remove_parent(child);
BUG_ON(!list_empty(&child->ptrace_entry));
list_add(&child->ptrace_entry, &new_parent->ptraced);
child->parent = new_parent;
add_parent(child);
}
/*
@ -73,12 +69,8 @@ void __ptrace_unlink(struct task_struct *child)
BUG_ON(!child->ptrace);
child->ptrace = 0;
if (ptrace_reparented(child)) {
list_del_init(&child->ptrace_list);
remove_parent(child);
child->parent = child->real_parent;
add_parent(child);
}
child->parent = child->real_parent;
list_del_init(&child->ptrace_entry);
if (task_is_traced(child))
ptrace_untrace(child);
@ -492,15 +484,34 @@ int ptrace_traceme(void)
/*
* Are we already being traced?
*/
repeat:
task_lock(current);
if (!(current->ptrace & PT_PTRACED)) {
/*
* See ptrace_attach() comments about the locking here.
*/
unsigned long flags;
if (!write_trylock_irqsave(&tasklist_lock, flags)) {
task_unlock(current);
do {
cpu_relax();
} while (!write_can_lock(&tasklist_lock));
goto repeat;
}
ret = security_ptrace(current->parent, current,
PTRACE_MODE_ATTACH);
/*
* Set the ptrace bit in the process ptrace flags.
* Then link us on our parent's ptraced list.
*/
if (!ret)
if (!ret) {
current->ptrace |= PT_PTRACED;
__ptrace_link(current, current->real_parent);
}
write_unlock_irqrestore(&tasklist_lock, flags);
}
task_unlock(current);
return ret;