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 *);
> 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.
I am afraid we'll have bash and perl in kernel before too long,
if this avenue is to be pursued.
Why don't you use something like SGI kdb for debugging kernels?
-- Pete
Can this kill kill dead die go away forever D state processes?
David
S. Parker wrote:
> 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.
On Fri, 8 Feb 2002, Pete Zaitcev wrote:
> > 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.
>
> I am afraid we'll have bash and perl in kernel before too long,
> if this avenue is to be pursued.
>
> Why don't you use something like SGI kdb for debugging kernels?
Its very useful to have adequate debugging tools for productions systems.
Something like SGIs kdb is too heavyweight and is not in the mainline
linux kernel and will never, ever get pushed out to any of the production
systems that I work on. However, useful alt-sysrq tools to do post-mortem
analysis of crashed production kernels is something which is extremely
helpful.
What would be *really* useful would be to have crash dump functionality in
the mainline linux kernel. That way you could take a dump and then do
your post-mortem offline with a debugger. Until then I'm all in favor of
throwing bloat into alt-sysrq, since that seems to be Linus' preferred
interface for doing post-mortem analysis.
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.
Looks good to me; (maybe you could reuse from 'kIll' as killing of all
processes is hardly ever usefull).
Pavel
--
(about SSSCA) "I don't say this lightly. However, I really think that the U.S.
no longer is classifiable as a democracy, but rather as a plutocracy." --hpa
I certainly have no particular preference for what this is called.
Is there support for dropping the existing kIll and me re-submitting
these changes that way? (I've never imagined how kIll actually helped.)
Cheers,
~sparker
At 12:19 PM 2/9/2002 , Pavel Machek wrote:
>Hi!
>
> >
> > 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.
>
>Looks good to me; (maybe you could reuse from 'kIll' as killing of all
>processes is hardly ever usefull).
> Pavel
>--
>(about SSSCA) "I don't say this lightly. However, I really think that the
>U.S.
>no longer is classifiable as a democracy, but rather as a plutocracy." --hpa
Cheers,
~sparker