[PATCH] Show Mr. SIGKILL some R-E-S-P-E-C-T

From: Bhavesh P. Davda
Date: Sun Sep 18 2005 - 18:26:14 EST



Here's the scenario (single-threaded, multi-threaded doesn't matter)

# kill -STOP pid
# egrep "^State|^SigPnd|^ShdPnd" /proc/pid/status
State: T (stopped)
SigPnd: 0000000000000000
ShdPnd: 0000000000000000

The following command sends a signal to the specified thread ID using the
tkill(2) syscall interface

# tkill -ALRM pid (Or any other signal other than SIGCONT or SIGKILL)
# egrep "^State|^SigPnd|^ShdPnd" /proc/pid/status
State: T (stopped)
SigPnd: 0000000000002000 [ SIGALRM pending ]
ShdPnd: 0000000000000000

# kill -ABRT pid
# egrep "^State|^SigPnd|^ShdPnd" /proc/pid/status
State: T (stopped)
SigPnd: 0000000000002000 [ SIGALRM pending ]
ShdPnd: 0000000000000020 [ SIGABRT pending ]

# kill -KILL pid
# egrep "^State|^SigPnd|^ShdPnd" /proc/pid/status
State: T (stopped)
SigPnd: 0000000000002000 [ SIGALRM pending ]
ShdPnd: 0000000000000120 [ SIGABRT and SIGKILL pending ]

EGAD! SIGKILL should have whacked the pid, no matter what.

Here's a patch that fixes this.

Thanks!

- Bhavesh

Bhavesh P. Davda | Distinguished Member of Technical Staff | Avaya |
1300 West 120th Avenue | B3-B03 | Westminster, CO 80234 | U.S.A. |
Voice/Fax: 303.538.4438 | bhavesh@xxxxxxxxx
--- a/kernel/signal.c 2005-09-12 15:50:16.000000000 -0600
+++ b/kernel/signal.c 2005-09-17 12:04:58.898465728 -0600
@@ -935,10 +935,11 @@
* have pending signals. Such threads will dequeue from the shared queue
* as soon as they're available, so putting the signal on the shared queue
* will be equivalent to sending it to one such thread.
+ * Don't bother traced and stopped tasks
*/
-#define wants_signal(sig, p, mask) \
+#define wants_signal(sig, p) \
(!sigismember(&(p)->blocked, sig) \
- && !((p)->state & mask) \
+ && !((p)->state & (TASK_STOPPED|TASK_TRACED)) \
&& !((p)->flags & PF_EXITING) \
&& (task_curr(p) || !signal_pending(p)))

@@ -946,24 +947,17 @@
static void
__group_complete_signal(int sig, struct task_struct *p)
{
- unsigned int mask;
struct task_struct *t;

/*
- * Don't bother traced and stopped tasks (but
- * SIGKILL will punch through that).
- */
- mask = TASK_STOPPED | TASK_TRACED;
- if (sig == SIGKILL)
- mask = 0;
-
- /*
* Now find a thread we can wake up to take the signal off the queue.
*
* If the main thread wants the signal, it gets first crack.
* Probably the least surprising to the average bear.
+ *
+ * SIGKILL is always delivered to the main thread
*/
- if (wants_signal(sig, p, mask))
+ if ((sig == SIGKILL) || (wants_signal(sig, p)))
t = p;
else if (thread_group_empty(p))
/*
@@ -981,7 +975,7 @@
t = p->signal->curr_target = p;
BUG_ON(t->tgid != p->tgid);

- while (!wants_signal(sig, t, mask)) {
+ while (!wants_signal(sig, t)) {
t = next_thread(t);
if (t == p->signal->curr_target)
/*