ptrace: relocate set_current_state(TASK_TRACED) in ptrace_stop()
In ptrace_stop(), after arch hook is done, the task state and jobctl
bits are updated while holding siglock. The ordering requirement
there is that TASK_TRACED is set before JOBCTL_TRAPPING is cleared to
prevent ptracer waiting on TRAPPING doesn't end up waking up TRACED is
actually set and sees TASK_RUNNING in wait(2).
Move set_current_state(TASK_TRACED) to the top of the block and
reorganize comments. This makes the ordering more obvious
(TASK_TRACED before other updates) and helps future updates to group
stop participation.
This patch doesn't cause any functional change.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
diff --git a/kernel/signal.c b/kernel/signal.c
index ab6851c..62a6c3b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1733,6 +1733,18 @@
}
/*
+ * We're committing to trapping. TRACED should be visible before
+ * TRAPPING is cleared; otherwise, the tracer might fail do_wait().
+ * Also, transition to TRACED and updates to ->jobctl should be
+ * atomic with respect to siglock and should be done after the arch
+ * hook as siglock is released and regrabbed across it.
+ */
+ set_current_state(TASK_TRACED);
+
+ current->last_siginfo = info;
+ current->exit_code = exit_code;
+
+ /*
* If @why is CLD_STOPPED, we're trapping to participate in a group
* stop. Do the bookkeeping. Note that if SIGCONT was delievered
* while siglock was released for the arch hook, PENDING could be
@@ -1742,21 +1754,7 @@
if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING))
gstop_done = task_participate_group_stop(current);
- current->last_siginfo = info;
- current->exit_code = exit_code;
-
- /*
- * TRACED should be visible before TRAPPING is cleared; otherwise,
- * the tracer might fail do_wait().
- */
- set_current_state(TASK_TRACED);
-
- /*
- * We're committing to trapping. Clearing JOBCTL_TRAPPING and
- * transition to TASK_TRACED should be atomic with respect to
- * siglock. This should be done after the arch hook as siglock is
- * released and regrabbed across it.
- */
+ /* entering a trap, clear TRAPPING */
task_clear_jobctl_trapping(current);
spin_unlock_irq(¤t->sighand->siglock);