Introduce the "utrace-friendly" ptrace_wake_up() and use it instead of wake_up_process().
Kill ptrace_untrace(), detach should wake up the tracee correctly via UTRACE_DETACH. --- kernel/ptrace.c | 47 ++++++++++++++++++++--------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) --- MINI/kernel/ptrace.c~5_WAKEUP 2009-08-25 17:54:50.000000000 +0200 +++ MINI/kernel/ptrace.c 2009-08-25 18:09:38.000000000 +0200 @@ -98,6 +98,25 @@ void xxx_ptrace_notify_stop(struct task_ utrace_engine_put(engine); } +static void ptrace_wake_up(struct task_struct *task) +{ + struct utrace_engine *engine; + + engine = utrace_attach_task(task, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (unlikely(IS_ERR(engine))) + return; + + if (task_is_stopped_or_traced(task)) { + spin_lock_irq(&task->sighand->siglock); + task->signal->flags &= ~SIGNAL_STOP_STOPPED; + spin_unlock_irq(&task->sighand->siglock); + } + + utrace_control(task, engine, UTRACE_RESUME); + utrace_engine_put(engine); +} + /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -112,30 +131,6 @@ void __ptrace_link(struct task_struct *c } /* - * Turn a tracing stop into a normal stop now, since with no tracer there - * would be no way to wake it up with SIGCONT or SIGKILL. If there was a - * signal sent that would resume the child, but didn't because it was in - * TASK_TRACED, resume it now. - * Requires that irqs be disabled. - */ -static void ptrace_untrace(struct task_struct *child) -{ - spin_lock(&child->sighand->siglock); - if (task_is_traced(child)) { - /* - * If the group stop is completed or in progress, - * this thread was already counted as stopped. - */ - if (child->signal->flags & SIGNAL_STOP_STOPPED || - child->signal->group_stop_count) - __set_task_state(child, TASK_STOPPED); - else - signal_wake_up(child, 1); - } - spin_unlock(&child->sighand->siglock); -} - -/* * unptrace a task: move it back to its original parent and * remove it from the ptrace list. * @@ -150,8 +145,6 @@ void __ptrace_unlink(struct task_struct list_del_init(&child->ptrace_entry); arch_ptrace_untrace(child); - if (task_is_traced(child)) - ptrace_untrace(child); } /* @@ -590,7 +583,7 @@ static int ptrace_resume(struct task_str } child->exit_code = data; - wake_up_process(child); + ptrace_wake_up(child); return 0; }