aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/signal.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-09-23 16:22:21 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-23 16:22:21 -0400
commit188a1eafa03aaa5e5fe6f53e637e704cd2c31c7c (patch)
tree33d9480c792724c10e4e6fb681fc69c477cf1ff0 /kernel/signal.c
parentede1327ea4ca8019ec6df24b3e837def091c26b8 (diff)
Make sure SIGKILL gets proper respect
Bhavesh P. Davda <bhavesh@avaya.com> noticed that SIGKILL wouldn't properly kill a process under just the right cicumstances: a stopped task that already had another signal queued would get the SIGKILL queued onto the shared queue, and there it would remain until SIGCONT. This simplifies the signal acceptance logic, and fixes the bug in the process. Losely based on an earlier patch by Bhavesh. Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel/signal.c')
-rw-r--r--kernel/signal.c31
1 files changed, 14 insertions, 17 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index b92c3c9f8b9a..5a274705ba19 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -936,34 +936,31 @@ force_sig_specific(int sig, struct task_struct *t)
936 * as soon as they're available, so putting the signal on the shared queue 936 * as soon as they're available, so putting the signal on the shared queue
937 * will be equivalent to sending it to one such thread. 937 * will be equivalent to sending it to one such thread.
938 */ 938 */
939#define wants_signal(sig, p, mask) \ 939static inline int wants_signal(int sig, struct task_struct *p)
940 (!sigismember(&(p)->blocked, sig) \ 940{
941 && !((p)->state & mask) \ 941 if (sigismember(&p->blocked, sig))
942 && !((p)->flags & PF_EXITING) \ 942 return 0;
943 && (task_curr(p) || !signal_pending(p))) 943 if (p->flags & PF_EXITING)
944 944 return 0;
945 if (sig == SIGKILL)
946 return 1;
947 if (p->state & (TASK_STOPPED | TASK_TRACED))
948 return 0;
949 return task_curr(p) || !signal_pending(p);
950}
945 951
946static void 952static void
947__group_complete_signal(int sig, struct task_struct *p) 953__group_complete_signal(int sig, struct task_struct *p)
948{ 954{
949 unsigned int mask;
950 struct task_struct *t; 955 struct task_struct *t;
951 956
952 /* 957 /*
953 * Don't bother traced and stopped tasks (but
954 * SIGKILL will punch through that).
955 */
956 mask = TASK_STOPPED | TASK_TRACED;
957 if (sig == SIGKILL)
958 mask = 0;
959
960 /*
961 * Now find a thread we can wake up to take the signal off the queue. 958 * Now find a thread we can wake up to take the signal off the queue.
962 * 959 *
963 * If the main thread wants the signal, it gets first crack. 960 * If the main thread wants the signal, it gets first crack.
964 * Probably the least surprising to the average bear. 961 * Probably the least surprising to the average bear.
965 */ 962 */
966 if (wants_signal(sig, p, mask)) 963 if (wants_signal(sig, p))
967 t = p; 964 t = p;
968 else if (thread_group_empty(p)) 965 else if (thread_group_empty(p))
969 /* 966 /*
@@ -981,7 +978,7 @@ __group_complete_signal(int sig, struct task_struct *p)
981 t = p->signal->curr_target = p; 978 t = p->signal->curr_target = p;
982 BUG_ON(t->tgid != p->tgid); 979 BUG_ON(t->tgid != p->tgid);
983 980
984 while (!wants_signal(sig, t, mask)) { 981 while (!wants_signal(sig, t)) {
985 t = next_thread(t); 982 t = next_thread(t);
986 if (t == p->signal->curr_target) 983 if (t == p->signal->curr_target)
987 /* 984 /*