]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: sysrq: add ability for sysrq-x to signal chrome/X
authorSonny Rao <sonnyrao@chromium.org>
Mon, 10 Dec 2012 19:06:02 +0000 (11:06 -0800)
committerGerrit <chrome-bot@google.com>
Wed, 12 Dec 2012 21:37:26 +0000 (13:37 -0800)
Because we weren't getting reports of actual kernel issues, and
we've already trained some users to hit sysrq-x when the system
appears to freeze, we decided to have sysrq-x try a few other things
in addition to crashing the kernel.  For the first keypress it will
try to find the Chrome browser process, by looking for the one which
has the  session_manager as a parent, and send a SIGABRT to that.  If
there is a second sysrq-x within 5 seconds, it will send a SIGABRT to
the X process, and if there's a third then it will crash the kernel as
before.

BUG=chromium-os:36901
TEST=manual (debugging feature):
 hold down alt-volup then x - chrome should crash
 repeat immediately afterward - session should restart
 repeat and machine should reboot

Change-Id: I127256b7777aee4a4d84a958f2c061d7b6de318b
Signed-off-by: Sonny Rao <sonnyrao@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/39527
Reviewed-by: Sameer Nanda <snanda@chromium.org>
Reviewed-by: Olof Johansson <olofj@chromium.org>
drivers/tty/sysrq.c

index 4796af7c377a4baa68dc350099d25ee1a2e64c3b..460998928668b094059b586f6563058f9ad3a3f7 100644 (file)
@@ -399,12 +399,72 @@ static struct sysrq_key_op sysrq_unrt_op = {
        .enable_mask    = SYSRQ_ENABLE_RTNICE,
 };
 
+/* send a signal to a process named comm if it has a certain parent */
+/* if parent is NULL, send to the first matching process */
+static void sysrq_x_cros_signal_process(char *comm, char *parent, int sig)
+{
+       struct task_struct *p;
+
+       read_lock(&tasklist_lock);
+       for_each_process(p) {
+               if (p->flags & PF_KTHREAD)
+                       continue;
+               if (is_global_init(p))
+                       continue;
+
+               if (!strncmp(p->comm, comm, TASK_COMM_LEN)) {
+                       if (!parent) {
+                               printk(KERN_INFO
+                                      "%s: signal %d %s pid %u tgid %u\n",
+                                      __func__, sig, comm, p->pid, p->tgid);
+                               do_send_sig_info(sig, SEND_SIG_FORCED, p,
+                                                true);
+                               break;
+                       } else if (p->parent &&
+                                  !strncmp(p->parent->comm, parent,
+                                         TASK_COMM_LEN)) {
+                               printk(KERN_INFO
+                                      "%s: signal %d %s with parent %s "
+                                      "pid %u tgid %u\n",
+                                      __func__, sig,
+                                      comm, parent, p->parent->pid,
+                                      p->parent->tgid);
+                               do_send_sig_info(sig, SEND_SIG_FORCED, p,
+                                                true);
+                               break;
+                       }
+               }
+       }
+       read_unlock(&tasklist_lock);
+}
+
+/* how many seconds do we wait for subsequent keypresses after the first */
+#define CROS_SYSRQ_WAIT 20
+
 static void sysrq_handle_cros_xkey(int key)
 {
-       sysrq_handle_showstate_blocked(key);
-       sysrq_handle_sync(key);
-       mdelay(1000); /* Delay for a bit to give time for sync to complete */
-       panic("ChromeOS X Key");
+       static unsigned long first_jiffies;
+       static unsigned int xkey_iteration;
+
+       if ((!first_jiffies) ||
+           (jiffies - first_jiffies) > CROS_SYSRQ_WAIT * HZ) {
+               first_jiffies = jiffies;
+               xkey_iteration = 0;
+       } else
+               xkey_iteration++;
+
+       if (!xkey_iteration)
+               sysrq_x_cros_signal_process("chrome", "session_manager",
+                                           SIGABRT);
+       else if (xkey_iteration == 1)
+               sysrq_x_cros_signal_process("X", NULL, SIGABRT);
+       else {
+               sysrq_handle_showstate_blocked(key);
+               sysrq_handle_sync(key);
+               /* Delay for a bit to give time for sync to complete */
+               mdelay(1000);
+               panic("ChromeOS X Key");
+       }
 }
 
 static struct sysrq_key_op sysrq_cros_xkey = {