[mutter/wip/carlosg/xwayland-startup-side-channel: 3/5] wayland: Set up initialization X11 socket



commit 53019eb8f8ebba0acc4d74027c39fa2778b2f740
Author: Carlos Garnacho <carlosg gnome org>
Date:   Fri Jul 19 22:50:31 2019 +0200

    wayland: Set up initialization X11 socket
    
    This is used by GDK and the X11 bits, but may also be used for
    other initialization services we might need to run along with
    Xwayland initialization.
    
    However, as the -initfd argument in Xwayland is a fairly new
    feature, add some fallback code so we handle older Xwayland
    versions. The only drawback is that initialization won't be
    synchronous to the client on Xwayland-on-demand, but that's
    how it is already.

 src/wayland/meta-wayland-private.h | 11 ++++-
 src/wayland/meta-wayland.c         |  4 +-
 src/wayland/meta-xwayland.c        | 93 ++++++++++++++++++++++++++++----------
 3 files changed, 82 insertions(+), 26 deletions(-)
---
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index 9b99674e0..9ecf9bc24 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -48,11 +48,18 @@ typedef struct
   char *lock_file;
   int abstract_fd;
   int unix_fd;
+  char *name;
+} MetaXWaylandConnection;
+
+typedef struct
+{
+  MetaXWaylandConnection private_connection;
+  MetaXWaylandConnection public_connection;
+
   guint xserver_grace_period_id;
   struct wl_display *wayland_display;
   struct wl_client *client;
   struct wl_resource *xserver_resource;
-  char *display_name;
   char *auth_file;
 
   GCancellable *xserver_died_cancellable;
@@ -62,6 +69,8 @@ typedef struct
   GList *x11_windows;
 
   MetaXWaylandDnd *dnd;
+
+  gboolean failed_initfd;
 } MetaXWaylandManager;
 
 struct _MetaWaylandCompositor
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 806c897c9..da19ec955 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -445,7 +445,7 @@ meta_wayland_init (void)
 
   if (meta_get_x11_display_policy () != META_DISPLAY_POLICY_DISABLED)
     {
-      set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor));
+      set_gnome_env ("DISPLAY", compositor->xwayland_manager.public_connection.name);
       set_gnome_env ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor));
     }
 
@@ -461,7 +461,7 @@ meta_wayland_get_wayland_display_name (MetaWaylandCompositor *compositor)
 const char *
 meta_wayland_get_xwayland_display_name (MetaWaylandCompositor *compositor)
 {
-  return compositor->xwayland_manager.display_name;
+  return compositor->xwayland_manager.private_connection.name;
 }
 
 void
diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c
index 1ea9df7e6..ed11e37b0 100644
--- a/src/wayland/meta-xwayland.c
+++ b/src/wayland/meta-xwayland.c
@@ -72,6 +72,7 @@ G_DEFINE_TYPE (MetaWaylandSurfaceRoleXWayland,
 
 static int display_number_override = -1;
 
+static gboolean meta_xwayland_start_xserver (MetaXWaylandManager *manager);
 static void meta_xwayland_stop_xserver (MetaXWaylandManager *manager);
 
 void
@@ -361,7 +362,9 @@ xserver_died (GObject      *source,
               GAsyncResult *result,
               gpointer      user_data)
 {
+  MetaXWaylandManager *manager = user_data;
   GSubprocess *proc = G_SUBPROCESS (source);
+  MetaDisplay *display = meta_get_display ();
   g_autoptr (GError) error = NULL;
 
   if (!g_subprocess_wait_finish (proc, result, &error))
@@ -373,6 +376,13 @@ xserver_died (GObject      *source,
     }
   else if (!g_subprocess_get_successful (proc))
     {
+      if (!display->x11_display && !manager->failed_initfd)
+        {
+          manager->failed_initfd = TRUE;
+          meta_xwayland_start_xserver (manager);
+          return;
+        }
+
       if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_MANDATORY)
         g_warning ("X Wayland crashed; exiting");
       else
@@ -386,7 +396,6 @@ xserver_died (GObject      *source,
   else if (meta_get_x11_display_policy () == META_DISPLAY_POLICY_ON_DEMAND)
     {
       MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
-      MetaDisplay *display = meta_get_display ();
 
       if (display->x11_display)
         meta_display_shutdown_x11 (display);
@@ -429,6 +438,8 @@ meta_xwayland_override_display_number (int number)
 static gboolean
 open_display_sockets (MetaXWaylandManager *manager,
                       int                  display_index,
+                      int                 *abstract_fd_out,
+                      int                 *unix_fd_out,
                       gboolean            *fatal)
 {
   int abstract_fd, unix_fd;
@@ -446,14 +457,15 @@ open_display_sockets (MetaXWaylandManager *manager,
       return FALSE;
     }
 
-  manager->abstract_fd = abstract_fd;
-  manager->unix_fd = unix_fd;
+  *abstract_fd_out = abstract_fd;
+  *unix_fd_out = unix_fd;
 
   return TRUE;
 }
 
 static gboolean
-choose_xdisplay (MetaXWaylandManager *manager)
+choose_xdisplay (MetaXWaylandManager    *manager,
+                 MetaXWaylandConnection *connection)
 {
   int display = 0;
   char *lock_file = NULL;
@@ -473,7 +485,10 @@ choose_xdisplay (MetaXWaylandManager *manager)
           return FALSE;
         }
 
-      if (!open_display_sockets (manager, display, &fatal))
+      if (!open_display_sockets (manager, display,
+                                 &connection->abstract_fd,
+                                 &connection->unix_fd,
+                                 &fatal))
         {
           unlink (lock_file);
 
@@ -493,9 +508,9 @@ choose_xdisplay (MetaXWaylandManager *manager)
     }
   while (1);
 
-  manager->display_index = display;
-  manager->display_name = g_strdup_printf (":%d", manager->display_index);
-  manager->lock_file = lock_file;
+  connection->display_index = display;
+  connection->name = g_strdup_printf (":%d", connection->display_index);
+  connection->lock_file = lock_file;
 
   return TRUE;
 }
@@ -622,7 +637,8 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager)
   GSubprocessFlags flags;
   GError *error = NULL;
   const char *args [] = {
-    XWAYLAND_PATH, manager->display_name,
+    XWAYLAND_PATH,
+    manager->public_connection.name,
     "-rootless",
     "-noreset",
     "-accessx",
@@ -631,6 +647,8 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager)
     "-listen", "4",
     "-listen", "5",
     "-displayfd", "6",
+    /* NB: These must stay as the final arguments */
+    "-initfd", "7",
     NULL
   };
 
@@ -660,12 +678,19 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager)
   launcher = g_subprocess_launcher_new (flags);
 
   g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3);
-  g_subprocess_launcher_take_fd (launcher, manager->abstract_fd, 4);
-  g_subprocess_launcher_take_fd (launcher, manager->unix_fd, 5);
+  g_subprocess_launcher_take_fd (launcher, manager->public_connection.abstract_fd, 4);
+  g_subprocess_launcher_take_fd (launcher, manager->public_connection.unix_fd, 5);
   g_subprocess_launcher_take_fd (launcher, displayfd[1], 6);
+  g_subprocess_launcher_take_fd (launcher, manager->private_connection.abstract_fd, 7);
 
   g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
 
+  /* If we had already tried -initfd but failed, we run on an older Xwayland,
+   * modify the last argument so we use plain -listen instead.
+   */
+  if (manager->failed_initfd)
+    args[G_N_ELEMENTS (args) - 3] = "-listen";
+
   manager->proc = g_subprocess_launcher_spawnv (launcher, args, &error);
 
   if (!manager->proc)
@@ -676,7 +701,7 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager)
 
   manager->xserver_died_cancellable = g_cancellable_new ();
   g_subprocess_wait_async (manager->proc, manager->xserver_died_cancellable,
-                           xserver_died, NULL);
+                           xserver_died, manager);
   g_unix_fd_add (displayfd[0], G_IO_IN, on_displayfd_ready, manager);
   manager->client = wl_client_create (manager->wayland_display,
                                       xwayland_client_fd[0]);
@@ -768,9 +793,11 @@ meta_xwayland_init (MetaXWaylandManager *manager,
   MetaDisplayPolicy policy;
   gboolean fatal;
 
-  if (!manager->display_name)
+  if (!manager->public_connection.name)
     {
-      if (!choose_xdisplay (manager))
+      if (!choose_xdisplay (manager, &manager->public_connection))
+        return FALSE;
+      if (!choose_xdisplay (manager, &manager->private_connection))
         return FALSE;
 
       if (!prepare_auth_file (manager))
@@ -778,7 +805,18 @@ meta_xwayland_init (MetaXWaylandManager *manager,
     }
   else
     {
-      if (!open_display_sockets (manager, manager->display_index, &fatal))
+      if (!open_display_sockets (manager,
+                                 manager->public_connection.display_index,
+                                 &manager->public_connection.abstract_fd,
+                                 &manager->public_connection.unix_fd,
+                                 &fatal))
+        return FALSE;
+
+      if (!open_display_sockets (manager,
+                                 manager->private_connection.display_index,
+                                 &manager->private_connection.abstract_fd,
+                                 &manager->private_connection.unix_fd,
+                                 &fatal))
         return FALSE;
     }
 
@@ -791,7 +829,7 @@ meta_xwayland_init (MetaXWaylandManager *manager,
     }
   else if (policy == META_DISPLAY_POLICY_ON_DEMAND)
     {
-      g_unix_fd_add (manager->abstract_fd, G_IO_IN,
+      g_unix_fd_add (manager->public_connection.abstract_fd, G_IO_IN,
                      xdisplay_connection_activity_cb, manager);
       return TRUE;
     }
@@ -845,20 +883,29 @@ meta_xwayland_shutdown (MetaXWaylandManager *manager)
 
   g_cancellable_cancel (manager->xserver_died_cancellable);
 
-  snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->display_index);
+  snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->public_connection.display_index);
+  unlink (path);
+
+  snprintf (path, sizeof path, "/tmp/.X11-unix/X%d", manager->private_connection.display_index);
   unlink (path);
 
-  g_clear_pointer (&manager->display_name, g_free);
+  g_clear_pointer (&manager->public_connection.name, g_free);
+  g_clear_pointer (&manager->private_connection.name, g_free);
+  if (manager->public_connection.lock_file)
+    {
+      unlink (manager->public_connection.lock_file);
+      g_clear_pointer (&manager->public_connection.lock_file, g_free);
+    }
+  if (manager->private_connection.lock_file)
+    {
+      unlink (manager->private_connection.lock_file);
+      g_clear_pointer (&manager->private_connection.lock_file, g_free);
+    }
   if (manager->auth_file)
     {
       unlink (manager->auth_file);
       g_clear_pointer (&manager->auth_file, g_free);
     }
-  if (manager->lock_file)
-    {
-      unlink (manager->lock_file);
-      g_clear_pointer (&manager->lock_file, g_free);
-    }
 }
 
 static void


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