Move the code which clears SIGNAL_STOP_STOPPED under "if (force_wakeup)".
Change ptrace_detach() accordingly. See also the next patch which
cleanups/fixes ptrace_wake_up().

Upstream logic:

        if detach is explicit, we should always wakeup the tracee,
        otherwise (exit_ptrace() path) we rely on ptrace_untrace()
        which checks SIGNAL_STOP_STOPPED.

utrace-ptrace:

        ptrace_detach(sig) checks valid_signal(sig) to detect the
        explicit detach and passes "bool voluntary" to ptrace_wake_up().

both upstream and utrace-ptrace are racy (but these races are
different), hopefully utrace-ptrace is not worse. And of course
this all is not right and should be fixed, but we seem to agree
this should be fixed later, when utrace-ptrace is merged.


In my opinion, from now utrace-ptrace is close enough to upstream
wrt stop/wakeup oddities. It passes all tests which upstream passes,
plus it passes detach-stopped which fails with upstream kernel.

This is because utrace_get_signal() sets SIGNAL_STOP_DEQUEUED when
it returns a sig_kernel_stop() signal. This logic is not exactly
right, but I think it is better than nothing.


IOW: afaics we don't need additional functional changes in this area
before submitting utrace-ptrace. Of course, it is easy to detect the
difference in behaviour and perhaps we will have "it breaks my app"
reports, but I don't think we should try hard to be more bug-compatible
before V1.

What do you think?

---

 kernel/ptrace.c |   31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

--- PU/kernel/ptrace.c~90_DETACH_CK_IMPLICIT    2009-10-13 19:55:25.000000000 
+0200
+++ PU/kernel/ptrace.c  2009-10-14 13:18:45.000000000 +0200
@@ -82,7 +82,8 @@ static int ptrace_attach_task(struct tas
 static void ptrace_abort_attach(struct task_struct *tracee);
 static void ptrace_wake_up(struct task_struct *tracee,
                                struct utrace_engine *engine,
-                               enum utrace_resume_action action);
+                               enum utrace_resume_action action,
+                               bool force_wakeup);
 
 static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee)
 {
@@ -92,8 +93,9 @@ static struct utrace_engine *ptrace_look
 
 static void ptrace_detach_task(struct task_struct *tracee, int sig)
 {
-       struct utrace_engine *engine = ptrace_lookup_engine(tracee);
+       bool voluntary = valid_signal(sig);
        enum utrace_resume_action action = UTRACE_DETACH;
+       struct utrace_engine *engine = ptrace_lookup_engine(tracee);
 
        if (unlikely(IS_ERR(engine)))
                return;
@@ -104,12 +106,12 @@ static void ptrace_detach_task(struct ta
                switch (get_stop_event(context)) {
                case PTRACE_EVENT_SYSCALL_ENTRY:
                case PTRACE_EVENT_SYSCALL_EXIT:
-                       if (valid_signal(sig))
+                       if (voluntary)
                                send_sig_info(sig, SEND_SIG_PRIV, tracee);
                        break;
 
                case PTRACE_EVENT_SIGNAL:
-                       if (valid_signal(sig))
+                       if (voluntary)
                                context->signr = sig;
                        context->resume = UTRACE_DETACH;
                        action = UTRACE_RESUME;
@@ -117,7 +119,7 @@ static void ptrace_detach_task(struct ta
                }
        }
 
-       ptrace_wake_up(tracee, engine, action);
+       ptrace_wake_up(tracee, engine, action, voluntary);
        utrace_engine_put(engine);
 }
 
@@ -944,15 +946,18 @@ void ptrace_notify_stop(struct task_stru
 
 static void ptrace_wake_up( struct task_struct *tracee,
                                struct utrace_engine *engine,
-                               enum utrace_resume_action action)
+                               enum utrace_resume_action action,
+                               bool force_wakeup)
 {
-       unsigned long flags;
+       if (force_wakeup) {
+               unsigned long flags;
 
-       /* preserve the compatibility bug */
-       if (!lock_task_sighand(tracee, &flags))
-               return;
-       tracee->signal->flags &= ~SIGNAL_STOP_STOPPED;
-       unlock_task_sighand(tracee, &flags);
+               /* preserve the compatibility bug */
+               if (!lock_task_sighand(tracee, &flags))
+                       return;
+               tracee->signal->flags &= ~SIGNAL_STOP_STOPPED;
+               unlock_task_sighand(tracee, &flags);
+       }
 
        // XXX: FIXME!!! racy.
        tracee->exit_code = 0;
@@ -1012,7 +1017,7 @@ static void do_ptrace_resume(struct utra
        }
 
        context->resume = action;
-       ptrace_wake_up(tracee, engine, action);
+       ptrace_wake_up(tracee, engine, action, true);
 }
 
 static int ptrace_resume(struct utrace_engine *engine,

Reply via email to