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
This commit is contained in:
Giovanni Campagna 2013-07-16 16:39:32 +02:00
parent fc42b478bd
commit fa3ca2bf10
3 changed files with 46 additions and 7 deletions

View File

@ -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"))

View File

@ -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);

View File

@ -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 */