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;
        }

Reply via email to