From fa3ca2bf10feff59324459f685a5f4bf7301158a Mon Sep 17 00:00:00 2001 From: Giovanni Campagna Date: Tue, 16 Jul 2013 16:39:32 +0200 Subject: [PATCH] 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. https://bugzilla.gnome.org/show_bug.cgi?id=705861 --- src/core/main.c | 35 +++++++++++++++++++++++++++++++++++ src/wayland/meta-tty.c | 15 ++++++++------- src/wayland/meta-tty.h | 3 +++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index f762f59c7..5799fe596 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -365,6 +365,28 @@ 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: %d\n", 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 */ + if (tty) + meta_tty_reset (tty, FALSE); + + /* We can't continue with the default handling, so just exit here */ + _exit(1); +} + /** * meta_init: (skip) * @@ -390,6 +412,19 @@ meta_init (void) g_strerror (errno)); #endif + if (meta_is_wayland_compositor ()) + { + 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); + } + g_unix_signal_add (SIGTERM, on_sigterm, NULL); if (g_getenv ("MUTTER_VERBOSE")) diff --git a/src/wayland/meta-tty.c b/src/wayland/meta-tty.c index fe867c0ff..bb735afcb 100644 --- a/src/wayland/meta-tty.c +++ b/src/wayland/meta-tty.c @@ -334,22 +334,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) @@ -374,7 +375,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 f5a24644b..bf3dd5155 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 */