diff options
author | Tejun Heo <tj@kernel.org> | 2011-06-02 05:13:59 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2011-06-04 12:17:10 -0400 |
commit | 81be24b8cdeb69e62f9d1b6b425fd9ffdd37f581 (patch) | |
tree | 63afd141fdb380c7b00a01a2080ace6bcc232386 /kernel/signal.c | |
parent | 755e276b3326f300585435d2f3876e66e248c476 (diff) |
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.c | 28 |
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) | |||
1733 | } | 1733 | } |
1734 | 1734 | ||
1735 | /* | 1735 | /* |
1736 | * We're committing to trapping. TRACED should be visible before | ||
1737 | * TRAPPING is cleared; otherwise, the tracer might fail do_wait(). | ||
1738 | * Also, transition to TRACED and updates to ->jobctl should be | ||
1739 | * atomic with respect to siglock and should be done after the arch | ||
1740 | * hook as siglock is released and regrabbed across it. | ||
1741 | */ | ||
1742 | set_current_state(TASK_TRACED); | ||
1743 | |||
1744 | current->last_siginfo = info; | ||
1745 | current->exit_code = exit_code; | ||
1746 | |||
1747 | /* | ||
1736 | * If @why is CLD_STOPPED, we're trapping to participate in a group | 1748 | * If @why is CLD_STOPPED, we're trapping to participate in a group |
1737 | * stop. Do the bookkeeping. Note that if SIGCONT was delievered | 1749 | * stop. Do the bookkeeping. Note that if SIGCONT was delievered |
1738 | * while siglock was released for the arch hook, PENDING could be | 1750 | * 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) | |||
1742 | if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING)) | 1754 | if (why == CLD_STOPPED && (current->jobctl & JOBCTL_STOP_PENDING)) |
1743 | gstop_done = task_participate_group_stop(current); | 1755 | gstop_done = task_participate_group_stop(current); |
1744 | 1756 | ||
1745 | current->last_siginfo = info; | 1757 | /* entering a trap, clear TRAPPING */ |
1746 | current->exit_code = exit_code; | ||
1747 | |||
1748 | /* | ||
1749 | * TRACED should be visible before TRAPPING is cleared; otherwise, | ||
1750 | * the tracer might fail do_wait(). | ||
1751 | */ | ||
1752 | set_current_state(TASK_TRACED); | ||
1753 | |||
1754 | /* | ||
1755 | * We're committing to trapping. Clearing JOBCTL_TRAPPING and | ||
1756 | * transition to TASK_TRACED should be atomic with respect to | ||
1757 | * siglock. This should be done after the arch hook as siglock is | ||
1758 | * released and regrabbed across it. | ||
1759 | */ | ||
1760 | task_clear_jobctl_trapping(current); | 1758 | task_clear_jobctl_trapping(current); |
1761 | 1759 | ||
1762 | spin_unlock_irq(¤t->sighand->siglock); | 1760 | spin_unlock_irq(¤t->sighand->siglock); |