[mutter] x11: close display in an idle function



commit 31f525d5668f80f2b6bd66eaaf23102b6b82f4c2
Author: Andrea Azzarone <azzaronea gmail com>
Date:   Wed Oct 31 14:21:40 2018 +0000

    x11: close display in an idle function
    
    Closing a GdkDisplay during an event handler is not currently supported by Gdk
    and it will result in a crash when doing e.g. 'mutter --replace'. Using an idle
    function will close it safely in a subsequent main loop iteration.
    
    Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/595

 src/x11/events.c                   | 28 +++++++++++++++++++++-------
 src/x11/meta-x11-display-private.h |  3 +++
 src/x11/meta-x11-display.c         |  9 +++++++++
 3 files changed, 33 insertions(+), 7 deletions(-)
---
diff --git a/src/x11/events.c b/src/x11/events.c
index 59caeb4b9..1e77538db 100644
--- a/src/x11/events.c
+++ b/src/x11/events.c
@@ -1138,6 +1138,18 @@ process_selection_request (MetaX11Display *x11_display,
   meta_verbose ("Handled selection request\n");
 }
 
+static gboolean
+close_display_idle_cb (gpointer user_data)
+{
+  MetaX11Display *x11_display = META_X11_DISPLAY (user_data);
+
+  meta_display_close (x11_display->display,
+                      x11_display->xselectionclear_timestamp);
+  x11_display->display_close_idle = 0;
+
+  return G_SOURCE_REMOVE;
+}
+
 static gboolean
 process_selection_clear (MetaX11Display *x11_display,
                          XEvent         *event)
@@ -1163,8 +1175,13 @@ process_selection_clear (MetaX11Display *x11_display,
   meta_verbose ("Got selection clear for on display %s\n",
                 x11_display->name);
 
-  meta_display_close (x11_display->display,
-                      event->xselectionclear.time);
+  /* We can't close a GdkDisplay in an even handler. */
+  if (!x11_display->display_close_idle)
+    {
+      x11_display->xselectionclear_timestamp = event->xselectionclear.time;
+      x11_display->display_close_idle = g_idle_add (close_display_idle_cb, x11_display);
+    }
+
   return TRUE;
 }
 
@@ -1818,11 +1835,8 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display,
     {
       if (process_selection_clear (x11_display, event))
         {
-          /* This means we called meta_display_unmanage_screen, which
-           * means the MetaDisplay is effectively dead. We don't want
-           * to poke into display->current_time below, since that would
-           * crash, so just directly return. */
-          return TRUE;
+          bypass_gtk = TRUE;
+          goto out;
         }
     }
 
diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h
index 05019e8cf..fdd642bbc 100644
--- a/src/x11/meta-x11-display-private.h
+++ b/src/x11/meta-x11-display-private.h
@@ -92,6 +92,9 @@ struct _MetaX11Display
   Atom wm_sn_atom;
   guint32 wm_sn_timestamp;
 
+  guint display_close_idle;
+  guint32 xselectionclear_timestamp;
+
   Window wm_cm_selection_window;
 
   Window composite_overlay_window;
diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c
index 83f7dfbae..4a6d64e08 100644
--- a/src/x11/meta-x11-display.c
+++ b/src/x11/meta-x11-display.c
@@ -215,6 +215,12 @@ meta_x11_display_dispose (GObject *object)
       x11_display->gdk_display = NULL;
     }
 
+  if (x11_display->display_close_idle)
+    {
+      g_source_remove (x11_display->display_close_idle);
+      x11_display->display_close_idle = 0;
+    }
+
   g_free (x11_display->name);
   x11_display->name = NULL;
 
@@ -1186,6 +1192,9 @@ meta_x11_display_new (MetaDisplay *display, GError **error)
   x11_display->timestamp_pinging_window = None;
   x11_display->wm_sn_selection_window = None;
 
+  x11_display->display_close_idle = 0;
+  x11_display->xselectionclear_timestamp = 0;
+
   x11_display->last_bell_time = 0;
   x11_display->focus_serial = 0;
   x11_display->server_focus_window = None;


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