[mutter/+wip/wayland-2: 10/10] Add a crash handler to restore the TTY and keyboard mode



commit b066797f36b436dd30c2819595828782fa8f1e2a
Author: Giovanni Campagna <gcampagn redhat com>
Date:   Tue Jul 16 16:39:32 2013 +0200

    Add a crash handler to restore the TTY and keyboard mode
    
    If mutter crashes on secondary VT, it leaves you with a raw keyboard
    that doesn't switch with Alt+FN and no way to get out. At least,
    let's provide a decent error message that we crash and let's
    restore everything to sane defaults.

 src/core/main.c        |   34 ++++++++++++++++++++++++++++++++++
 src/wayland/meta-tty.c |   15 ++++++++-------
 src/wayland/meta-tty.h |    3 +++
 3 files changed, 45 insertions(+), 7 deletions(-)
---
diff --git a/src/core/main.c b/src/core/main.c
index d545576..16c51da 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -365,6 +365,27 @@ on_sigterm (gpointer user_data)
   return G_SOURCE_REMOVE;
 }
 
+static void
+crash_handler (int signum)
+{
+  char buffer[256];
+  MetaWaylandCompositor *compositor;
+  MetaTTY *tty;
+
+  snprintf (buffer, 256, "Fatal server error: %s\n", strsignal (signum));
+  write (STDERR_FILENO, buffer, strlen (buffer));
+
+  compositor = meta_wayland_compositor_get_default ();
+  tty = meta_wayland_compositor_get_tty (compositor);
+
+  /* Passing FALSE ensures that we only do ioctls, which is
+     safe from a signal handler */
+  meta_tty_reset (tty, FALSE);
+
+  /* We can't continue with the default handling, so just exit here */
+  _exit(1);
+}
+
 /**
  * meta_init: (skip)
  *
@@ -390,6 +411,19 @@ meta_init (void)
                 g_strerror (errno));
 #endif
 
+  if (meta_is_display_server ())
+    {
+      act.sa_handler = crash_handler;
+
+      /* Ignore if we can't register signal handlers, worse
+         that can happen one needs the sysrq to get out of the VT */
+      sigaction (SIGABRT, &act, NULL);
+      sigaction (SIGSEGV, &act, NULL);
+      sigaction (SIGBUS, &act, NULL);
+      sigaction (SIGFPE, &act, NULL);
+      sigaction (SIGTRAP, &act, NULL);
+    }
+
   /* Revert weston-launch brokenness */
   sigemptyset (&empty_mask);
   sigaddset (&empty_mask, SIGTERM);
diff --git a/src/wayland/meta-tty.c b/src/wayland/meta-tty.c
index b0161a4..c3a5a97 100644
--- a/src/wayland/meta-tty.c
+++ b/src/wayland/meta-tty.c
@@ -332,22 +332,23 @@ meta_tty_initable_init(GInitable     *initable,
   return FALSE;
 }
 
-static void
-tty_reset (MetaTTY *tty)
+void
+meta_tty_reset (MetaTTY  *tty,
+               gboolean  warn_if_fail)
 {
   struct vt_mode mode = { 0 };
 
-  if (ioctl (tty->fd, KDSKBMODE, tty->kb_mode))
+  if (ioctl (tty->fd, KDSKBMODE, tty->kb_mode) && warn_if_fail)
     g_warning ("failed to restore keyboard mode: %s", strerror (errno));
 
-  if (ioctl (tty->fd, KDSETMODE, KD_TEXT))
+  if (ioctl (tty->fd, KDSETMODE, KD_TEXT) && warn_if_fail)
     g_warning ("failed to set KD_TEXT mode on tty: %s", strerror (errno));
 
-  if (tcsetattr (tty->fd, TCSANOW, &tty->terminal_attributes) < 0)
+  if (tcsetattr (tty->fd, TCSANOW, &tty->terminal_attributes) < 0 && warn_if_fail)
     g_warning ("could not restore terminal to canonical mode");
 
   mode.mode = VT_AUTO;
-  if (ioctl (tty->fd, VT_SETMODE, &mode) < 0)
+  if (ioctl (tty->fd, VT_SETMODE, &mode) < 0 && warn_if_fail)
     g_warning ("could not reset vt handling\n");
 
   if (tty->vt != tty->starting_vt)
@@ -372,7 +373,7 @@ meta_tty_finalize (GObject *object)
   g_main_loop_unref (tty->nested_loop);
   g_main_context_unref (tty->nested_context);
 
-  tty_reset (tty);
+  meta_tty_reset (tty, TRUE);
 
   close (tty->fd);
 
diff --git a/src/wayland/meta-tty.h b/src/wayland/meta-tty.h
index f5a2464..bf3dd51 100644
--- a/src/wayland/meta-tty.h
+++ b/src/wayland/meta-tty.h
@@ -42,6 +42,9 @@ gboolean          meta_tty_activate_vt             (MetaTTY  *self,
                                                    int       number,
                                                    GError  **error);
 
+void              meta_tty_reset                   (MetaTTY  *self,
+                                                   gboolean  warn_if_fail);
+
 G_END_DECLS
 
 #endif /* META_TTY_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]