diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-01-21 14:47:41 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-22 11:50:08 -0500 |
commit | 910ffdb18a6408e14febbb6e4b6840fd2c928c82 (patch) | |
tree | 258a215685f2ca2bb11dcd92582e0adafbd83f7b /kernel | |
parent | 9a9284153d965a57edc7162a8e57c14c97f3a935 (diff) |
ptrace: introduce signal_wake_up_state() and ptrace_signal_wake_up()
Cleanup and preparation for the next change.
signal_wake_up(resume => true) is overused. None of ptrace/jctl callers
actually want to wakeup a TASK_WAKEKILL task, but they can't specify the
necessary mask.
Turn signal_wake_up() into signal_wake_up_state(state), reintroduce
signal_wake_up() as a trivial helper, and add ptrace_signal_wake_up()
which adds __TASK_TRACED.
This way ptrace_signal_wake_up() can work "inside" ptrace_request()
even if the tracee doesn't have the TASK_WAKEKILL bit set.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/ptrace.c | 8 | ||||
-rw-r--r-- | kernel/signal.c | 14 |
2 files changed, 8 insertions, 14 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 612a56126851..62f7c2774b16 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -117,7 +117,7 @@ void __ptrace_unlink(struct task_struct *child) | |||
117 | * TASK_KILLABLE sleeps. | 117 | * TASK_KILLABLE sleeps. |
118 | */ | 118 | */ |
119 | if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) | 119 | if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child)) |
120 | signal_wake_up(child, task_is_traced(child)); | 120 | ptrace_signal_wake_up(child, true); |
121 | 121 | ||
122 | spin_unlock(&child->sighand->siglock); | 122 | spin_unlock(&child->sighand->siglock); |
123 | } | 123 | } |
@@ -317,7 +317,7 @@ static int ptrace_attach(struct task_struct *task, long request, | |||
317 | */ | 317 | */ |
318 | if (task_is_stopped(task) && | 318 | if (task_is_stopped(task) && |
319 | task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) | 319 | task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING)) |
320 | signal_wake_up(task, 1); | 320 | signal_wake_up_state(task, __TASK_STOPPED); |
321 | 321 | ||
322 | spin_unlock(&task->sighand->siglock); | 322 | spin_unlock(&task->sighand->siglock); |
323 | 323 | ||
@@ -737,7 +737,7 @@ int ptrace_request(struct task_struct *child, long request, | |||
737 | * tracee into STOP. | 737 | * tracee into STOP. |
738 | */ | 738 | */ |
739 | if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) | 739 | if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP))) |
740 | signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); | 740 | ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING); |
741 | 741 | ||
742 | unlock_task_sighand(child, &flags); | 742 | unlock_task_sighand(child, &flags); |
743 | ret = 0; | 743 | ret = 0; |
@@ -763,7 +763,7 @@ int ptrace_request(struct task_struct *child, long request, | |||
763 | * start of this trap and now. Trigger re-trap. | 763 | * start of this trap and now. Trigger re-trap. |
764 | */ | 764 | */ |
765 | if (child->jobctl & JOBCTL_TRAP_NOTIFY) | 765 | if (child->jobctl & JOBCTL_TRAP_NOTIFY) |
766 | signal_wake_up(child, true); | 766 | ptrace_signal_wake_up(child, true); |
767 | ret = 0; | 767 | ret = 0; |
768 | } | 768 | } |
769 | unlock_task_sighand(child, &flags); | 769 | unlock_task_sighand(child, &flags); |
diff --git a/kernel/signal.c b/kernel/signal.c index 53cd5c4d1172..6e97aa6fa32c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -680,23 +680,17 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info) | |||
680 | * No need to set need_resched since signal event passing | 680 | * No need to set need_resched since signal event passing |
681 | * goes through ->blocked | 681 | * goes through ->blocked |
682 | */ | 682 | */ |
683 | void signal_wake_up(struct task_struct *t, int resume) | 683 | void signal_wake_up_state(struct task_struct *t, unsigned int state) |
684 | { | 684 | { |
685 | unsigned int mask; | ||
686 | |||
687 | set_tsk_thread_flag(t, TIF_SIGPENDING); | 685 | set_tsk_thread_flag(t, TIF_SIGPENDING); |
688 | |||
689 | /* | 686 | /* |
690 | * For SIGKILL, we want to wake it up in the stopped/traced/killable | 687 | * TASK_WAKEKILL also means wake it up in the stopped/traced/killable |
691 | * case. We don't check t->state here because there is a race with it | 688 | * case. We don't check t->state here because there is a race with it |
692 | * executing another processor and just now entering stopped state. | 689 | * executing another processor and just now entering stopped state. |
693 | * By using wake_up_state, we ensure the process will wake up and | 690 | * By using wake_up_state, we ensure the process will wake up and |
694 | * handle its death signal. | 691 | * handle its death signal. |
695 | */ | 692 | */ |
696 | mask = TASK_INTERRUPTIBLE; | 693 | if (!wake_up_state(t, state | TASK_INTERRUPTIBLE)) |
697 | if (resume) | ||
698 | mask |= TASK_WAKEKILL; | ||
699 | if (!wake_up_state(t, mask)) | ||
700 | kick_process(t); | 694 | kick_process(t); |
701 | } | 695 | } |
702 | 696 | ||
@@ -844,7 +838,7 @@ static void ptrace_trap_notify(struct task_struct *t) | |||
844 | assert_spin_locked(&t->sighand->siglock); | 838 | assert_spin_locked(&t->sighand->siglock); |
845 | 839 | ||
846 | task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); | 840 | task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY); |
847 | signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); | 841 | ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING); |
848 | } | 842 | } |
849 | 843 | ||
850 | /* | 844 | /* |