It doesn't make sense to reset engine->context unless we know we are going to re-use it, move this code to ptrace_reuse_engine().
Except: ptrace_detach_task() has to clear context->stop_code (it is checked by ptrace_report_signal()) and tracee->exit_code. This will be removed later, when we change detach to use ptrace_wake_up(action) instead of utrace_control(). Also, improve the comments. --- kernel/ptrace.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) --- PU/kernel/ptrace.c~87_SHIFT_REINIT_TO_REUSE 2009-10-13 17:36:05.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 18:14:55.000000000 +0200 @@ -107,18 +107,11 @@ static void ptrace_detach_task(struct ta break; case PTRACE_EVENT_SIGNAL: + /* make sure do_wait() can't succeed */ + tracee->exit_code = 0; if (valid_signal(sig)) context->signr = sig; - context->options = 0; - context->eventmsg = 0; context->stop_code = 0; - /* make sure do_wait() can't succeed */ - tracee->exit_code = 0; - utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); - /* - * once we set UTRACE_DETACH we don't own this engine, - * utrace_set_events() also acts as a memory barrier. - */ context->resume = UTRACE_DETACH; action = UTRACE_RESUME; break; @@ -434,11 +427,23 @@ ptrace_reuse_engine(struct task_struct * context = ptrace_context(engine); if (unlikely(context->resume == UTRACE_DETACH)) { - /* we rely on ->cred_guard_mutex */ - context->resume = UTRACE_RESUME; - /* make sure we don't race with ptrace_report_signal() */ - err = utrace_barrier(tracee, engine); + /* + * Try to reuse this self-detaching engine. + * The only caller which can hit this case is ptrace_attach(), + * it holds ->cred_guard_mutex. + */ + context->options = 0; + context->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + context->resume = UTRACE_RESUME; + /* synchronize with ptrace_report_signal() */ + err = utrace_barrier(tracee, engine); + } WARN_ON(!err != (engine->ops == &ptrace_utrace_ops)); + if (!err) return engine; }