wayland: Set IO error exit handler

If this call is available, we can turn libX11 IO errors (fatal by definition)
into something we can recover from. Try to dispose all X11 resources and close
the display instead, so the compositor can survive the event.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1447
This commit is contained in:
Carlos Garnacho 2019-06-14 16:04:44 +02:00
parent 1b39b92fa5
commit f4a1dcfc93
3 changed files with 28 additions and 0 deletions

View File

@ -71,6 +71,9 @@
/* Whether Xwayland has -initfd option */
#mesondefine HAVE_XWAYLAND_INITFD
/* Whether libX11 has XSetIOErrorExitHandler */
#mesondefine HAVE_XSETIOERROREXITHANDLER
/* Whether the mkostemp function exists */
#mesondefine HAVE_MKOSTEMP

View File

@ -424,6 +424,13 @@ if have_wayland
endif
endif
have_xsetioerrorexithandler = false
if cc.has_function('XSetIOErrorExitHandler', dependencies: x11_dep,
prefix: '''#include <X11/Xlib.h>''')
have_xsetioerrorexithandler = true
cdata.set('HAVE_XSETIOERROREXITHANDLER', 1)
endif
optional_functions = [
'mkostemp',
'posix_fallocate',
@ -495,6 +502,7 @@ output = [
' Introspection............ ' + have_introspection.to_string(),
' Profiler................. ' + have_profiler.to_string(),
' Xwayland initfd.......... ' + have_xwayland_initfd.to_string(),
' Safe X11 I/O errors...... ' + have_xsetioerrorexithandler.to_string(),
'',
' Tests:',
'',

View File

@ -334,6 +334,20 @@ x_io_error (Display *display)
return 0;
}
#ifdef HAVE_XSETIOERROREXITHANDLER
static void
x_io_error_exit (Display *display,
MetaX11Display *x11_display)
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
MetaXWaylandManager *manager = &compositor->xwayland_manager;
g_warning ("Xwayland just died, attempting to recover");
manager->xserver_grace_period_id =
g_idle_add (shutdown_xwayland_cb, manager);
}
#endif
void
meta_xwayland_override_display_number (int number)
{
@ -795,6 +809,9 @@ meta_xwayland_complete_init (MetaDisplay *display,
we won't reset the tty).
*/
XSetIOErrorHandler (x_io_error);
#ifdef HAVE_XSETIOERROREXITHANDLER
XSetIOErrorExitHandler (xdisplay, x_io_error_exit, display);
#endif
g_signal_connect (display, "x11-display-closing",
G_CALLBACK (on_x11_display_closing), NULL);