summaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-06-02 11:13:59 +0200
committerOleg Nesterov <oleg@redhat.com>2011-06-04 18:17:10 +0200
commit81be24b8cdeb69e62f9d1b6b425fd9ffdd37f581 (patch)
tree63afd141fdb380c7b00a01a2080ace6bcc232386 /kernel/signal.c
parent755e276b3326f300585435d2f3876e66e248c476 (diff)
downloadlinux-stable-81be24b8cdeb69e62f9d1b6b425fd9ffdd37f581.tar.gz
linux-stable-81be24b8cdeb69e62f9d1b6b425fd9ffdd37f581.tar.bz2
linux-stable-81be24b8cdeb69e62f9d1b6b425fd9ffdd37f581.zip
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>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index ab6851c06461..62a6c3bb9f0d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1733,6 +1733,18 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
}
/*
+ * 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 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
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(&current->sighand->siglock);