diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-07-25 04:47:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-25 13:53:39 -0400 |
commit | 3d749b9e676b26584a47e75c235aa6f69d0697ae (patch) | |
tree | 2db2dab84cde07c4872ac5e8d4078f2a3fc4271d /kernel/signal.c | |
parent | 364d3c13c17f45da6d638011078d4c4d3070d719 (diff) |
ptrace: simplify ptrace_stop()->sigkill_pending() path
1. SIGKILL can't be blocked, remove this check from sigkill_pending().
2. When ptrace_stop() sees sigkill_pending() == T, it can just return.
Kill "int killed" and simplify the code. This also is more correct,
the tracer shouldn't see us in TASK_TRACED if we are not going to
stop.
I strongly believe this code needs further changes. We should do the "was
this task killed" check unconditionally, currently it depends on
arch_ptrace_stop_needed(). On the other hand, sigkill_pending() isn't
very clever. If the task was killed tkill(SIGKILL), the signal can be
already dequeued if the caller is do_exit().
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r-- | kernel/signal.c | 12 |
1 files changed, 5 insertions, 7 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index fdab7b363fa7..39c1706edf03 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -1496,9 +1496,8 @@ static inline int may_ptrace_stop(void) | |||
1496 | */ | 1496 | */ |
1497 | static int sigkill_pending(struct task_struct *tsk) | 1497 | static int sigkill_pending(struct task_struct *tsk) |
1498 | { | 1498 | { |
1499 | return ((sigismember(&tsk->pending.signal, SIGKILL) || | 1499 | return sigismember(&tsk->pending.signal, SIGKILL) || |
1500 | sigismember(&tsk->signal->shared_pending.signal, SIGKILL)) && | 1500 | sigismember(&tsk->signal->shared_pending.signal, SIGKILL); |
1501 | !unlikely(sigismember(&tsk->blocked, SIGKILL))); | ||
1502 | } | 1501 | } |
1503 | 1502 | ||
1504 | /* | 1503 | /* |
@@ -1514,8 +1513,6 @@ static int sigkill_pending(struct task_struct *tsk) | |||
1514 | */ | 1513 | */ |
1515 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | 1514 | static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) |
1516 | { | 1515 | { |
1517 | int killed = 0; | ||
1518 | |||
1519 | if (arch_ptrace_stop_needed(exit_code, info)) { | 1516 | if (arch_ptrace_stop_needed(exit_code, info)) { |
1520 | /* | 1517 | /* |
1521 | * The arch code has something special to do before a | 1518 | * The arch code has something special to do before a |
@@ -1531,7 +1528,8 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
1531 | spin_unlock_irq(¤t->sighand->siglock); | 1528 | spin_unlock_irq(¤t->sighand->siglock); |
1532 | arch_ptrace_stop(exit_code, info); | 1529 | arch_ptrace_stop(exit_code, info); |
1533 | spin_lock_irq(¤t->sighand->siglock); | 1530 | spin_lock_irq(¤t->sighand->siglock); |
1534 | killed = sigkill_pending(current); | 1531 | if (sigkill_pending(current)) |
1532 | return; | ||
1535 | } | 1533 | } |
1536 | 1534 | ||
1537 | /* | 1535 | /* |
@@ -1548,7 +1546,7 @@ static void ptrace_stop(int exit_code, int clear_code, siginfo_t *info) | |||
1548 | __set_current_state(TASK_TRACED); | 1546 | __set_current_state(TASK_TRACED); |
1549 | spin_unlock_irq(¤t->sighand->siglock); | 1547 | spin_unlock_irq(¤t->sighand->siglock); |
1550 | read_lock(&tasklist_lock); | 1548 | read_lock(&tasklist_lock); |
1551 | if (!unlikely(killed) && may_ptrace_stop()) { | 1549 | if (may_ptrace_stop()) { |
1552 | do_notify_parent_cldstop(current, CLD_TRAPPED); | 1550 | do_notify_parent_cldstop(current, CLD_TRAPPED); |
1553 | read_unlock(&tasklist_lock); | 1551 | read_unlock(&tasklist_lock); |
1554 | schedule(); | 1552 | schedule(); |