sched,signal,ptrace: Rework TASK_TRACED, TASK_STOPPED state
[linux-2.6-block.git] / kernel / ptrace.c
index 36a5b7a00d2f2295cb75e38c52e8045422ec213d..328a34a991248923d564a76e87d588e4562bb9ff 100644 (file)
@@ -185,7 +185,12 @@ static bool looks_like_a_spurious_pid(struct task_struct *task)
        return true;
 }
 
-/* Ensure that nothing can wake it up, even SIGKILL */
+/*
+ * Ensure that nothing can wake it up, even SIGKILL
+ *
+ * A task is switched to this state while a ptrace operation is in progress;
+ * such that the ptrace operation is uninterruptible.
+ */
 static bool ptrace_freeze_traced(struct task_struct *task)
 {
        bool ret = false;
@@ -216,8 +221,10 @@ static void ptrace_unfreeze_traced(struct task_struct *task)
         */
        if (lock_task_sighand(task, &flags)) {
                task->jobctl &= ~JOBCTL_PTRACE_FROZEN;
-               if (__fatal_signal_pending(task))
+               if (__fatal_signal_pending(task)) {
+                       task->jobctl &= ~TASK_TRACED;
                        wake_up_state(task, __TASK_TRACED);
+               }
                unlock_task_sighand(task, &flags);
        }
 }
@@ -462,8 +469,10 @@ static int ptrace_attach(struct task_struct *task, long request,
         * in and out of STOPPED are protected by siglock.
         */
        if (task_is_stopped(task) &&
-           task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
+           task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) {
+               task->jobctl &= ~JOBCTL_STOPPED;
                signal_wake_up_state(task, __TASK_STOPPED);
+       }
 
        spin_unlock(&task->sighand->siglock);
 
@@ -875,6 +884,7 @@ static int ptrace_resume(struct task_struct *child, long request,
         */
        spin_lock_irq(&child->sighand->siglock);
        child->exit_code = data;
+       child->jobctl &= ~JOBCTL_TRACED;
        wake_up_state(child, __TASK_TRACED);
        spin_unlock_irq(&child->sighand->siglock);