lkml.org 
[lkml]   [2002]   [Feb]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectSysrq enhancement: process kill facility
Hi,

Here's something that myself and others at Cobalt Networks have found useful.
It extends sysrq to support a way to manually kill a process. In debugging
situations, we have found times where the system gets wedged, and we'ld like
to avoid a reboot. Show tasks provides the pid information.

You enter <alt>-<sysrq>-n ("nuke"), and then prompts for the pid. It supports
backspace and control-U. On serial ports, it retains the same semantics:
a break activates this as a sysrq sequence, but if more than 5-seconds pass
without any input, it drops out of processing input as a sysrq.

Feedback welcome, please cc: me directly.

Cheers,

~sparker


diff -ur generic-2.4.17/drivers/char/keyboard.c
sysrq-generic-2.4.17/drivers/char/keyboard.c
--- generic-2.4.17/drivers/char/keyboard.c Tue Sep 18 13:39:51 2001
+++ sysrq-generic-2.4.17/drivers/char/keyboard.c Thu Feb 7 17:59:18
2002
@@ -252,7 +252,7 @@
goto out;
} else if (sysrq_pressed) {
if (!up_flag) {
- handle_sysrq(kbd_sysrq_xlate[keycode], kbd_pt_regs,
kbd, tty);
+ (void) handle_sysrq(kbd_sysrq_xlate[keycode],
kbd_pt_regs, kbd, tty);
goto out;
}
}
Only in sysrq-generic-2.4.17/drivers/char: keyboard.c.orig
diff -ur generic-2.4.17/drivers/char/serial.c
sysrq-generic-2.4.17/drivers/char/serial.c
--- generic-2.4.17/drivers/char/serial.c Fri Dec 21 09:41:54 2001
+++ sysrq-generic-2.4.17/drivers/char/serial.c Thu Feb 7 17:59:18 2002
@@ -645,8 +645,12 @@
if (break_pressed && info->line == sercons.index) {
if (ch != 0 &&
time_before(jiffies, break_pressed + HZ*5)) {
- handle_sysrq(ch, regs, NULL, NULL);
- break_pressed = 0;
+ if (!handle_sysrq(ch, regs, NULL, NULL)) {
+ break_pressed = 0;
+ } else {
+ /* reset time-out! more data needed */
+ break_pressed = jiffies;
+ }
goto ignore_char;
}
break_pressed = 0;
Only in sysrq-generic-2.4.17/drivers/char: serial.c.orig
diff -ur generic-2.4.17/drivers/char/serial_amba.c
sysrq-generic-2.4.17/drivers/char/serial_amba.c
--- generic-2.4.17/drivers/char/serial_amba.c Sun Sep 16 21:23:14 2001
+++ sysrq-generic-2.4.17/drivers/char/serial_amba.c Thu Feb 7 17:59:18
2002
@@ -356,8 +356,11 @@
#ifdef SUPPORT_SYSRQ
if (info->sysrq) {
if (ch && time_before(jiffies, info->sysrq)) {
- handle_sysrq(ch, regs, NULL, NULL);
- info->sysrq = 0;
+ if (!handle_sysrq(ch, regs, NULL, NULL)) {
+ info->sysrq = 0;
+ } else {
+ info->sysrq = jiffies;
+ }
goto ignore_char;
}
info->sysrq = 0;
diff -ur generic-2.4.17/drivers/char/sysrq.c
sysrq-generic-2.4.17/drivers/char/sysrq.c
--- generic-2.4.17/drivers/char/sysrq.c Fri Dec 21 09:41:54 2001
+++ sysrq-generic-2.4.17/drivers/char/sysrq.c Thu Feb 7 17:59:18 2002
@@ -42,13 +42,14 @@
void (*sysrq_power_off)(void);

/* Loglevel sysrq handler */
-static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
int i;
i = key - '0';
console_loglevel = 7;
printk("Loglevel set to %d\n", i);
console_loglevel = i;
+ return 0;
}
static struct sysrq_key_op sysrq_loglevel_op = {
handler: sysrq_handle_loglevel,
@@ -59,11 +60,12 @@

/* SAK sysrq handler */
#ifdef CONFIG_VT
-static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
if (tty)
do_SAK(tty);
reset_vc(fg_console);
+ return 0;
}
static struct sysrq_key_op sysrq_SAK_op = {
handler: sysrq_handle_SAK,
@@ -74,10 +76,11 @@


/* unraw sysrq handler */
-static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
if (kbd)
kbd->kbdmode = VC_XLATE;
+ return 0;
}
static struct sysrq_key_op sysrq_unraw_op = {
handler: sysrq_handle_unraw,
@@ -87,9 +90,10 @@


/* reboot sysrq handler */
-static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
machine_restart(NULL);
+ return 0;
}
static struct sysrq_key_op sysrq_reboot_op = {
handler: sysrq_handle_reboot,
@@ -217,10 +221,11 @@
console_loglevel = orig_loglevel;
}

-static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_sync(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
emergency_sync_scheduled = EMERG_SYNC;
wakeup_bdflush();
+ return 0;
}
static struct sysrq_key_op sysrq_sync_op = {
handler: sysrq_handle_sync,
@@ -228,10 +233,11 @@
action_msg: "Emergency Sync",
};

-static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
emergency_sync_scheduled = EMERG_REMOUNT;
wakeup_bdflush();
+ return 0;
}
static struct sysrq_key_op sysrq_mountro_op = {
handler: sysrq_handle_mountro,
@@ -244,10 +250,11 @@

/* SHOW SYSRQ HANDLERS BLOCK */

-static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
if (pt_regs)
show_regs(pt_regs);
+ return 0;
}
static struct sysrq_key_op sysrq_showregs_op = {
handler: sysrq_handle_showregs,
@@ -256,9 +263,10 @@
};


-static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
show_state();
+ return 0;
}
static struct sysrq_key_op sysrq_showstate_op = {
handler: sysrq_handle_showstate,
@@ -267,9 +275,10 @@
};


-static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
show_mem();
+ return 0;
}
static struct sysrq_key_op sysrq_showmem_op = {
handler: sysrq_handle_showmem,
@@ -277,6 +286,73 @@
action_msg: "Show Memory",
};

+void
+ask_to_kill(buf)
+{
+ char *p;
+ pid_t pid;
+ int errors;
+
+ for (p = buf; *p; p++) {
+ if (*p < '0' || *p > '9') {
+ printk("Bad pid: %s\n", buf);
+ return;
+ }
+ }
+ /* Okay, got a numeric string... */
+ for (p = buf, pid =0; *p; p++) {
+ pid *= 10;
+ pid += *p - '0';
+ }
+ errors = kill_proc(pid, SIGKILL, 1);
+ printk("kill: %d - returns %d\n", pid, errors);
+}
+int in_accumulate;
+char buf[128];
+
+static int
+accumulate_buf(char c)
+{
+ static int i = 0;
+
+ if (c == '\n' || c == '\r') {
+ buf[i] = '\0';
+ printk("\n");
+ ask_to_kill(buf);
+ in_accumulate = 0;
+ i = 0;
+ return 0;
+ }
+ if (c == '\b' || c == '\0177') { /* backspace or delete? */
+ if (i > 0) {
+ i--;
+ printk("\b \b");
+ }
+ return 1;
+ }
+ if (c == '\025') { /* ^U? kill the whole entry */
+ i = 0;
+ printk("XXX\nenter pid to kill: ");
+ return 1;
+ }
+ buf[i++] = c;
+ printk("%c", c);
+ return 1;
+}
+
+
+static int sysrq_handle_nuke(int key, struct pt_regs *pt_regs,
+ struct kbd_struct *kbd, struct tty_struct *tty) {
+ printk("enter pid to kill: ");
+ in_accumulate = 1;
+ return 1;
+}
+static struct sysrq_key_op sysrq_nuke_op = {
+ handler: sysrq_handle_nuke,
+ help_msg: "Nuke",
+ action_msg: "Nuke process",
+};
+
/* SHOW SYSRQ HANDLERS BLOCK */


@@ -299,10 +375,11 @@
}
}

-static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_term(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
send_sig_all(SIGTERM, 0);
console_loglevel = 8;
+ return 0;
}
static struct sysrq_key_op sysrq_term_op = {
handler: sysrq_handle_term,
@@ -310,10 +387,11 @@
action_msg: "Terminate All Tasks",
};

-static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_kill(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
send_sig_all(SIGKILL, 0);
console_loglevel = 8;
+ return 0;
}
static struct sysrq_key_op sysrq_kill_op = {
handler: sysrq_handle_kill,
@@ -321,10 +399,11 @@
action_msg: "Kill All Tasks",
};

-static void sysrq_handle_killall(int key, struct pt_regs *pt_regs,
+static int sysrq_handle_killall(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
send_sig_all(SIGKILL, 1);
console_loglevel = 8;
+ return 0;
}
static struct sysrq_key_op sysrq_killall_op = {
handler: sysrq_handle_killall,
@@ -368,7 +447,7 @@
#endif
/* l */ &sysrq_killall_op,
/* m */ &sysrq_showmem_op,
-/* n */ NULL,
+/* n */ &sysrq_nuke_op,
/* o */ NULL, /* This will often be registered
as 'Off' at init time */
/* p */ &sysrq_showregs_op,
@@ -431,14 +510,18 @@
* and any other keycode arrives.
*/

-void handle_sysrq(int key, struct pt_regs *pt_regs,
- struct kbd_struct *kbd, struct tty_struct *tty) {
+int handle_sysrq(int key, struct pt_regs *pt_regs,
+ struct kbd_struct *kbd, struct tty_struct *tty)
+{
+ int ret_val;
+
if (!sysrq_enabled)
- return;
+ return 0;

__sysrq_lock_table();
- __handle_sysrq_nolock(key, pt_regs, kbd, tty);
+ ret_val = __handle_sysrq_nolock(key, pt_regs, kbd, tty);
__sysrq_unlock_table();
+ return ret_val;
}

/*
@@ -447,14 +530,20 @@
* as they are inside of the lock
*/

-void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs,
+int __handle_sysrq_nolock(int key, struct pt_regs *pt_regs,
struct kbd_struct *kbd, struct tty_struct *tty) {
struct sysrq_key_op *op_p;
int orig_log_level;
int i, j;
+ int ret_val;

if (!sysrq_enabled)
- return;
+ return 0;
+
+ if (in_accumulate) {
+ ret_val = accumulate_buf(key);
+ return ret_val;
+ }

orig_log_level = console_loglevel;
console_loglevel = 7;
@@ -464,7 +553,7 @@
if (op_p) {
printk ("%s\n", op_p->action_msg);
console_loglevel = orig_log_level;
- op_p->handler(key, pt_regs, kbd, tty);
+ ret_val = op_p->handler(key, pt_regs, kbd, tty);
} else {
printk("HELP : ");
/* Only print the help msg once per handler */
@@ -476,7 +565,9 @@
}
printk ("\n");
console_loglevel = orig_log_level;
+ ret_val = 0;
}
+ return ret_val;
}

EXPORT_SYMBOL(handle_sysrq);
diff -ur generic-2.4.17/drivers/s390/char/ctrlchar.c
sysrq-generic-2.4.17/drivers/s390/char/ctrlchar.c
--- generic-2.4.17/drivers/s390/char/ctrlchar.c Sun Sep 30 12:26:07 2001
+++ sysrq-generic-2.4.17/drivers/s390/char/ctrlchar.c Thu Feb 7 17:59:18
2002
@@ -26,7 +26,7 @@

static void
ctrlchar_handle_sysrq(struct tty_struct *tty) {
- handle_sysrq(ctrlchar_sysrq_key, NULL, NULL, tty);
+ (void) handle_sysrq(ctrlchar_sysrq_key, NULL, NULL, tty);
}
#endif

diff -ur generic-2.4.17/drivers/tc/zs.c sysrq-generic-2.4.17/drivers/tc/zs.c
--- generic-2.4.17/drivers/tc/zs.c Mon Aug 27 08:56:31 2001
+++ sysrq-generic-2.4.17/drivers/tc/zs.c Thu Feb 7 17:59:18 2002
@@ -444,8 +444,12 @@
if (break_pressed && info->line == sercons.index) {
if (ch != 0 &&
time_before(jiffies, break_pressed + HZ*5)) {
- handle_sysrq(ch, regs, NULL, NULL);
- break_pressed = 0;
+ if (!handle_sysrq(ch, regs, NULL, NULL)) {
+ break_pressed = 0;
+ } else {
+ /* reset time-out! more data needed */
+ break_pressed = jiffies;
+ }
goto ignore_char;
}
break_pressed = 0;
diff -ur generic-2.4.17/include/linux/sysrq.h
sysrq-generic-2.4.17/include/linux/sysrq.h
--- generic-2.4.17/include/linux/sysrq.h Wed Jan 30 16:47:01 2002
+++ sysrq-generic-2.4.17/include/linux/sysrq.h Thu Feb 7 17:59:18 2002
@@ -18,7 +18,7 @@
struct tty_struct;

struct sysrq_key_op {
- void (*handler)(int, struct pt_regs *,
+ int (*handler)(int, struct pt_regs *,
struct kbd_struct *, struct tty_struct *);
char *help_msg;
char *action_msg;
@@ -29,9 +29,14 @@
/* Generic SysRq interface -- you may call it from any device driver,
supplying
* ASCII code of the key, pointer to registers and kbd/tty structs (if they
* are available -- else NULL's).
+ *
+ * Most sysrq's are single character commands, but to allow for multiple
+ * key-stroke input, handle_sysrq() returns true if the current command
+ * is collecting more input. This matters to serial-based consoles which
+ * base the interpretation of the character on the proximity of the break.
*/

-void handle_sysrq(int, struct pt_regs *,
+int handle_sysrq(int, struct pt_regs *,
struct kbd_struct *, struct tty_struct *);


@@ -40,7 +45,7 @@
* call sysrq handlers
*/

-void __handle_sysrq_nolock(int, struct pt_regs *,
+int __handle_sysrq_nolock(int, struct pt_regs *,
struct kbd_struct *, struct tty_struct *);



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:24    [W:0.077 / U:0.220 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site