Blame SOURCES/0050-Allow-sessions-to-register-with-GDM.patch

400dab
From d6aca6da3ab9c16e907c7f46cf6d7bc2abbc2890 Mon Sep 17 00:00:00 2001
400dab
From: Iain Lane <iainl@gnome.org>
400dab
Date: Tue, 7 May 2019 16:00:14 +0100
400dab
Subject: [PATCH 50/51] Allow sessions to register with GDM
400dab
MIME-Version: 1.0
400dab
Content-Type: text/plain; charset=UTF-8
400dab
Content-Transfer-Encoding: 8bit
400dab
400dab
Recording when sessions start, for Wayland → Xorg fallback or
400dab
transitioning to the user session, is currently done with timeouts.
400dab
400dab
This isn't ideal, because on some very slow machines the timeout can be
400dab
hit before the session has had a chance to fail: if gnome-session takes
400dab
more than 3 seconds to fail then the session will be considered to have
400dab
exited rather than failed, and so we don't do Xorg fallback.
400dab
400dab
We can do this more reliably if we allow sessions to optionally register
400dab
themselves with GDM. Then we will know when they've started, so can shut
400dab
down the greeter or fall back to Xorg as appropriate. The mechanism is
400dab
that they specify X-GDM-SessionRegisters=true in their file, and then
400dab
call RegsterSession on the DisplayManager interface on the bus (added in
400dab
the previous commit) to say that they've started up.
400dab
400dab
If X-GDM-SessionRegisters is missing or false, GDM will call the same
400dab
method for them after 10 seconds.
400dab
400dab
Closes: #483
400dab
---
400dab
 common/gdm-common.h                |  2 +
400dab
 daemon/gdm-display.c               | 19 ++-----
400dab
 daemon/gdm-local-display-factory.c | 49 +++++++++---------
400dab
 daemon/gdm-session.c               | 47 +++++++++++++++--
400dab
 daemon/gdm-session.h               |  1 +
400dab
 daemon/gdm-wayland-session.c       | 81 +++++++++++++++++++++++-------
400dab
 daemon/gdm-x-session.c             | 81 +++++++++++++++++++++++-------
400dab
 7 files changed, 201 insertions(+), 79 deletions(-)
400dab
400dab
diff --git a/common/gdm-common.h b/common/gdm-common.h
400dab
index 3fbf07653..7fd6458d7 100644
400dab
--- a/common/gdm-common.h
400dab
+++ b/common/gdm-common.h
400dab
@@ -1,59 +1,61 @@
400dab
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
400dab
  *
400dab
  * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
400dab
  *
400dab
  * This library is free software; you can redistribute it and/or
400dab
  * modify it under the terms of the GNU Library General Public
400dab
  * License as published by the Free Software Foundation; either
400dab
  * version 2 of the License, or (at your option) any later version.
400dab
  *
400dab
  * This library is distributed in the hope that it will be useful,
400dab
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
400dab
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
400dab
  * Library General Public License for more details.
400dab
  *
400dab
  * You should have received a copy of the GNU Library General Public
400dab
  * License along with this library; if not, write to the
400dab
  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
400dab
  * Boston, MA 02110-1301, USA.
400dab
  */
400dab
 
400dab
 #ifndef _GDM_COMMON_H
400dab
 #define _GDM_COMMON_H
400dab
 
400dab
 #include <glib-unix.h>
400dab
 #include <gio/gio.h>
400dab
 
400dab
 #include <pwd.h>
400dab
 #include <errno.h>
400dab
 
400dab
+#define REGISTER_SESSION_TIMEOUT 10
400dab
+
400dab
 #define        VE_IGNORE_EINTR(expr) \
400dab
         do {                         \
400dab
                 errno = 0;           \
400dab
                 expr;                \
400dab
         } while G_UNLIKELY (errno == EINTR);
400dab
 
400dab
 GQuark gdm_common_error_quark (void);
400dab
 #define GDM_COMMON_ERROR gdm_common_error_quark()
400dab
 
400dab
 typedef char * (*GdmExpandVarFunc) (const char *var,
400dab
                                     gpointer user_data);
400dab
 
400dab
 G_BEGIN_DECLS
400dab
 
400dab
 int            gdm_wait_on_pid           (int pid);
400dab
 int            gdm_wait_on_and_disown_pid (int pid,
400dab
                                            int timeout);
400dab
 int            gdm_signal_pid            (int pid,
400dab
                                           int signal);
400dab
 gboolean       gdm_get_pwent_for_name    (const char     *name,
400dab
                                           struct passwd **pwentp);
400dab
 
400dab
 gboolean       gdm_clear_close_on_exec_flag (int fd);
400dab
 
400dab
 const char *   gdm_make_temp_dir         (char    *template);
400dab
 
400dab
 char          *gdm_generate_random_bytes (gsize          size,
400dab
                                           GError       **error);
400dab
 gboolean       gdm_get_login_window_session_id (const char  *seat_id,
400dab
                                                 char       **session_id);
400dab
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
400dab
index 09cc2e116..ae20491cd 100644
400dab
--- a/daemon/gdm-display.c
400dab
+++ b/daemon/gdm-display.c
400dab
@@ -39,61 +39,60 @@
400dab
 
400dab
 #include "gdm-common.h"
400dab
 #include "gdm-display.h"
400dab
 #include "gdm-display-glue.h"
400dab
 #include "gdm-display-access-file.h"
400dab
 #include "gdm-launch-environment.h"
400dab
 
400dab
 #include "gdm-settings-direct.h"
400dab
 #include "gdm-settings-keys.h"
400dab
 
400dab
 #include "gdm-launch-environment.h"
400dab
 #include "gdm-dbus-util.h"
400dab
 
400dab
 #define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
400dab
 
400dab
 #define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
400dab
 
400dab
 struct GdmDisplayPrivate
400dab
 {
400dab
         char                 *id;
400dab
         char                 *seat_id;
400dab
         char                 *session_id;
400dab
         char                 *session_class;
400dab
         char                 *session_type;
400dab
 
400dab
         char                 *remote_hostname;
400dab
         int                   x11_display_number;
400dab
         char                 *x11_display_name;
400dab
         int                   status;
400dab
         time_t                creation_time;
400dab
-        GTimer               *server_timer;
400dab
 
400dab
         char                 *x11_cookie;
400dab
         gsize                 x11_cookie_size;
400dab
         GdmDisplayAccessFile *access_file;
400dab
 
400dab
         guint                 finish_idle_id;
400dab
 
400dab
         xcb_connection_t     *xcb_connection;
400dab
         int                   xcb_screen_number;
400dab
 
400dab
         GDBusConnection      *connection;
400dab
         GdmDisplayAccessFile *user_access_file;
400dab
 
400dab
         GdmDBusDisplay       *display_skeleton;
400dab
         GDBusObjectSkeleton  *object_skeleton;
400dab
 
400dab
         /* this spawns and controls the greeter session */
400dab
         GdmLaunchEnvironment *launch_environment;
400dab
 
400dab
         guint                 is_local : 1;
400dab
         guint                 is_initial : 1;
400dab
         guint                 allow_timed_login : 1;
400dab
         guint                 have_existing_user_accounts : 1;
400dab
         guint                 doing_initial_setup : 1;
400dab
         guint                 session_registered : 1;
400dab
 };
400dab
 
400dab
 enum {
400dab
         PROP_0,
400dab
         PROP_ID,
400dab
@@ -510,62 +509,60 @@ gdm_display_prepare (GdmDisplay *self)
400dab
          * asynchronously
400dab
          */
400dab
         look_for_existing_users_sync (self);
400dab
 
400dab
         self->priv->doing_initial_setup = wants_initial_setup (self);
400dab
 
400dab
         g_object_ref (self);
400dab
         ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
400dab
         g_object_unref (self);
400dab
 
400dab
         return ret;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_manage (GdmDisplay *self)
400dab
 {
400dab
         gboolean res;
400dab
 
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         g_debug ("GdmDisplay: Managing display: %s", self->priv->id);
400dab
 
400dab
         /* If not explicitly prepared, do it now */
400dab
         if (self->priv->status == GDM_DISPLAY_UNMANAGED) {
400dab
                 res = gdm_display_prepare (self);
400dab
                 if (! res) {
400dab
                         return FALSE;
400dab
                 }
400dab
         }
400dab
 
400dab
-        g_timer_start (self->priv->server_timer);
400dab
-
400dab
         if (g_strcmp0 (self->priv->session_class, "greeter") == 0) {
400dab
                 if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
400dab
                         GDM_DISPLAY_GET_CLASS (self)->manage (self);
400dab
                 }
400dab
         }
400dab
 
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_finish (GdmDisplay *self)
400dab
 {
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         if (self->priv->finish_idle_id != 0) {
400dab
                 g_source_remove (self->priv->finish_idle_id);
400dab
                 self->priv->finish_idle_id = 0;
400dab
         }
400dab
 
400dab
         _gdm_display_set_status (self, GDM_DISPLAY_FINISHED);
400dab
 
400dab
         g_debug ("GdmDisplay: finish display");
400dab
 
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
 static void
400dab
 gdm_display_disconnect (GdmDisplay *self)
400dab
 {
400dab
         /* These 3 bits are reserved/unused by the X protocol */
400dab
@@ -576,85 +573,80 @@ gdm_display_disconnect (GdmDisplay *self)
400dab
 
400dab
         if (self->priv->xcb_connection == NULL) {
400dab
                 return;
400dab
         }
400dab
 
400dab
         setup = xcb_get_setup (self->priv->xcb_connection);
400dab
 
400dab
         /* resource_id_mask is the bits given to each client for
400dab
          * addressing resources */
400dab
         highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
400dab
         client_increment = setup->resource_id_mask + 1;
400dab
 
400dab
         /* Kill every client but ourselves, then close our own connection
400dab
          */
400dab
         for (client = 0;
400dab
              client <= highest_client;
400dab
              client += client_increment) {
400dab
 
400dab
                 if (client != setup->resource_id_base)
400dab
                         xcb_kill_client (self->priv->xcb_connection, client);
400dab
         }
400dab
 
400dab
         xcb_flush (self->priv->xcb_connection);
400dab
 
400dab
         g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_unmanage (GdmDisplay *self)
400dab
 {
400dab
-        gdouble elapsed;
400dab
-
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         g_debug ("GdmDisplay: unmanage display");
400dab
 
400dab
         gdm_display_disconnect (self);
400dab
 
400dab
-        g_timer_stop (self->priv->server_timer);
400dab
-
400dab
         if (self->priv->user_access_file != NULL) {
400dab
                 gdm_display_access_file_close (self->priv->user_access_file);
400dab
                 g_object_unref (self->priv->user_access_file);
400dab
                 self->priv->user_access_file = NULL;
400dab
         }
400dab
 
400dab
         if (self->priv->access_file != NULL) {
400dab
                 gdm_display_access_file_close (self->priv->access_file);
400dab
                 g_object_unref (self->priv->access_file);
400dab
                 self->priv->access_file = NULL;
400dab
         }
400dab
 
400dab
-        elapsed = g_timer_elapsed (self->priv->server_timer, NULL);
400dab
-        if (elapsed < 3) {
400dab
-                g_warning ("GdmDisplay: display lasted %lf seconds", elapsed);
400dab
+        if (!self->priv->session_registered) {
400dab
+                g_warning ("GdmDisplay: Session never registered, failing");
400dab
                 _gdm_display_set_status (self, GDM_DISPLAY_FAILED);
400dab
         } else {
400dab
                 _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
400dab
         }
400dab
 
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_get_id (GdmDisplay         *self,
400dab
                     char              **id,
400dab
                     GError            **error)
400dab
 {
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         if (id != NULL) {
400dab
                 *id = g_strdup (self->priv->id);
400dab
         }
400dab
 
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_get_x11_display_name (GdmDisplay   *self,
400dab
                                   char        **x11_display,
400dab
                                   GError      **error)
400dab
 {
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         if (x11_display != NULL) {
400dab
@@ -898,61 +890,61 @@ gdm_display_get_property (GObject        *object,
400dab
         case PROP_X11_DISPLAY_NAME:
400dab
                 g_value_set_string (value, self->priv->x11_display_name);
400dab
                 break;
400dab
         case PROP_X11_COOKIE:
400dab
                 g_value_set_string (value, self->priv->x11_cookie);
400dab
                 break;
400dab
         case PROP_X11_AUTHORITY_FILE:
400dab
                 g_value_take_string (value,
400dab
                                      self->priv->access_file?
400dab
                                      gdm_display_access_file_get_path (self->priv->access_file) : NULL);
400dab
                 break;
400dab
         case PROP_IS_LOCAL:
400dab
                 g_value_set_boolean (value, self->priv->is_local);
400dab
                 break;
400dab
         case PROP_IS_CONNECTED:
400dab
                 g_value_set_boolean (value, self->priv->xcb_connection != NULL);
400dab
                 break;
400dab
         case PROP_LAUNCH_ENVIRONMENT:
400dab
                 g_value_set_object (value, self->priv->launch_environment);
400dab
                 break;
400dab
         case PROP_IS_INITIAL:
400dab
                 g_value_set_boolean (value, self->priv->is_initial);
400dab
                 break;
400dab
         case PROP_HAVE_EXISTING_USER_ACCOUNTS:
400dab
                 g_value_set_boolean (value, self->priv->have_existing_user_accounts);
400dab
                 break;
400dab
         case PROP_DOING_INITIAL_SETUP:
400dab
                 g_value_set_boolean (value, self->priv->doing_initial_setup);
400dab
                 break;
400dab
         case PROP_SESSION_REGISTERED:
400dab
-                g_value_set_boolean (value, priv->session_registered);
400dab
+                g_value_set_boolean (value, self->priv->session_registered);
400dab
                 break;
400dab
         case PROP_ALLOW_TIMED_LOGIN:
400dab
                 g_value_set_boolean (value, self->priv->allow_timed_login);
400dab
                 break;
400dab
         default:
400dab
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
400dab
                 break;
400dab
         }
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 handle_get_id (GdmDBusDisplay        *skeleton,
400dab
                GDBusMethodInvocation *invocation,
400dab
                GdmDisplay            *self)
400dab
 {
400dab
         char *id;
400dab
 
400dab
         gdm_display_get_id (self, &id, NULL);
400dab
 
400dab
         gdm_dbus_display_complete_get_id (skeleton, invocation, id);
400dab
 
400dab
         g_free (id);
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 handle_get_remote_hostname (GdmDBusDisplay        *skeleton,
400dab
                             GDBusMethodInvocation *invocation,
400dab
                             GdmDisplay            *self)
400dab
 {
400dab
@@ -1251,99 +1243,94 @@ gdm_display_class_init (GdmDisplayClass *klass)
400dab
                                                                FALSE,
400dab
                                                                G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
400dab
 
400dab
         g_object_class_install_property (object_class,
400dab
                                          PROP_LAUNCH_ENVIRONMENT,
400dab
                                          g_param_spec_object ("launch-environment",
400dab
                                                               NULL,
400dab
                                                               NULL,
400dab
                                                               GDM_TYPE_LAUNCH_ENVIRONMENT,
400dab
                                                               G_PARAM_READWRITE));
400dab
         g_object_class_install_property (object_class,
400dab
                                          PROP_STATUS,
400dab
                                          g_param_spec_int ("status",
400dab
                                                            "status",
400dab
                                                            "status",
400dab
                                                            -1,
400dab
                                                            G_MAXINT,
400dab
                                                            GDM_DISPLAY_UNMANAGED,
400dab
                                                            G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
400dab
 
400dab
         g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
400dab
 }
400dab
 
400dab
 static void
400dab
 gdm_display_init (GdmDisplay *self)
400dab
 {
400dab
 
400dab
         self->priv = GDM_DISPLAY_GET_PRIVATE (self);
400dab
 
400dab
         self->priv->creation_time = time (NULL);
400dab
-        self->priv->server_timer = g_timer_new ();
400dab
 }
400dab
 
400dab
 static void
400dab
 gdm_display_finalize (GObject *object)
400dab
 {
400dab
         GdmDisplay *self;
400dab
 
400dab
         g_return_if_fail (object != NULL);
400dab
         g_return_if_fail (GDM_IS_DISPLAY (object));
400dab
 
400dab
         self = GDM_DISPLAY (object);
400dab
 
400dab
         g_return_if_fail (self->priv != NULL);
400dab
 
400dab
         g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id);
400dab
         g_free (self->priv->id);
400dab
         g_free (self->priv->seat_id);
400dab
         g_free (self->priv->session_class);
400dab
         g_free (self->priv->remote_hostname);
400dab
         g_free (self->priv->x11_display_name);
400dab
         g_free (self->priv->x11_cookie);
400dab
 
400dab
         g_clear_object (&self->priv->display_skeleton);
400dab
         g_clear_object (&self->priv->object_skeleton);
400dab
         g_clear_object (&self->priv->connection);
400dab
 
400dab
         if (self->priv->access_file != NULL) {
400dab
                 g_object_unref (self->priv->access_file);
400dab
         }
400dab
 
400dab
         if (self->priv->user_access_file != NULL) {
400dab
                 g_object_unref (self->priv->user_access_file);
400dab
         }
400dab
 
400dab
-        if (self->priv->server_timer != NULL) {
400dab
-                g_timer_destroy (self->priv->server_timer);
400dab
-        }
400dab
-
400dab
         G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
400dab
 }
400dab
 
400dab
 GDBusObjectSkeleton *
400dab
 gdm_display_get_object_skeleton (GdmDisplay *self)
400dab
 {
400dab
         return self->priv->object_skeleton;
400dab
 }
400dab
 
400dab
 static void
400dab
 on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
400dab
                                       GdmDisplay           *self)
400dab
 {
400dab
         char       *session_id;
400dab
 
400dab
         g_debug ("GdmDisplay: Greeter session opened");
400dab
         session_id = gdm_launch_environment_get_session_id (launch_environment);
400dab
         _gdm_display_set_session_id (self, session_id);
400dab
         g_free (session_id);
400dab
 }
400dab
 
400dab
 static void
400dab
 on_launch_environment_session_started (GdmLaunchEnvironment *launch_environment,
400dab
                                        GdmDisplay           *self)
400dab
 {
400dab
         g_debug ("GdmDisplay: Greeter started");
400dab
 }
400dab
 
400dab
 static void
400dab
 self_destruct (GdmDisplay *self)
400dab
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
400dab
index aae226750..35880563d 100644
400dab
--- a/daemon/gdm-local-display-factory.c
400dab
+++ b/daemon/gdm-local-display-factory.c
400dab
@@ -39,61 +39,60 @@
400dab
 #include "gdm-settings-keys.h"
400dab
 #include "gdm-settings-direct.h"
400dab
 #include "gdm-display-store.h"
400dab
 #include "gdm-local-display.h"
400dab
 #include "gdm-legacy-display.h"
400dab
 
400dab
 #define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
400dab
 
400dab
 #define GDM_DBUS_PATH                       "/org/gnome/DisplayManager"
400dab
 #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
400dab
 #define GDM_MANAGER_DBUS_NAME               "org.gnome.DisplayManager.LocalDisplayFactory"
400dab
 
400dab
 #define MAX_DISPLAY_FAILURES 5
400dab
 #define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
400dab
 
400dab
 struct GdmLocalDisplayFactoryPrivate
400dab
 {
400dab
         GdmDBusLocalDisplayFactory *skeleton;
400dab
         GDBusConnection *connection;
400dab
         GHashTable      *used_display_numbers;
400dab
 
400dab
         /* FIXME: this needs to be per seat? */
400dab
         guint            num_failures;
400dab
 
400dab
         guint            seat_new_id;
400dab
         guint            seat_removed_id;
400dab
 
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
         unsigned int     active_vt;
400dab
         guint            active_vt_watch_id;
400dab
-        guint            wait_to_finish_timeout_id;
400dab
 #endif
400dab
 };
400dab
 
400dab
 enum {
400dab
         PROP_0,
400dab
 };
400dab
 
400dab
 static void     gdm_local_display_factory_class_init    (GdmLocalDisplayFactoryClass *klass);
400dab
 static void     gdm_local_display_factory_init          (GdmLocalDisplayFactory      *factory);
400dab
 static void     gdm_local_display_factory_finalize      (GObject                     *object);
400dab
 
400dab
 static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory,
400dab
                                                          const char                  *seat_id,
400dab
                                                          const char                  *session_type,
400dab
                                                          gboolean                    initial_display);
400dab
 
400dab
 static void     on_display_status_changed               (GdmDisplay                  *display,
400dab
                                                          GParamSpec                  *arg1,
400dab
                                                          GdmLocalDisplayFactory      *factory);
400dab
 
400dab
 static gboolean gdm_local_display_factory_sync_seats    (GdmLocalDisplayFactory *factory);
400dab
 static gpointer local_display_factory_object = NULL;
400dab
 static gboolean lookup_by_session_id (const char *id,
400dab
                                       GdmDisplay *display,
400dab
                                       gpointer    user_data);
400dab
 
400dab
 G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
400dab
 
400dab
 GQuark
400dab
 gdm_local_display_factory_error_quark (void)
400dab
@@ -276,60 +275,79 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
400dab
 static gboolean
400dab
 finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
400dab
                                    GdmDisplay      *display,
400dab
                                    const char      *seat_id)
400dab
 {
400dab
         if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
400dab
                 return FALSE;
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: finish background display\n");
400dab
         gdm_display_stop_greeter_session (display);
400dab
         gdm_display_unmanage (display);
400dab
         gdm_display_finish (display);
400dab
 
400dab
         return FALSE;
400dab
 }
400dab
 
400dab
 static void
400dab
 finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory,
400dab
                                  const char             *seat_id)
400dab
 {
400dab
         GdmDisplayStore *store;
400dab
 
400dab
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
400dab
 
400dab
         gdm_display_store_foreach (store,
400dab
                                    (GdmDisplayStoreFunc) finish_display_on_seat_if_waiting,
400dab
                                    (gpointer)
400dab
                                    seat_id);
400dab
 }
400dab
 
400dab
+static void
400dab
+on_session_registered_cb (GObject *gobject,
400dab
+                          GParamSpec *pspec,
400dab
+                          gpointer user_data)
400dab
+{
400dab
+        GdmDisplay *display = GDM_DISPLAY (gobject);
400dab
+        GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
400dab
+        gboolean registered;
400dab
+
400dab
+        g_object_get (display, "session-registered", &registered, NULL);
400dab
+
400dab
+        if (!registered)
400dab
+                return;
400dab
+
400dab
+        g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill");
400dab
+
400dab
+        finish_waiting_displays_on_seat (factory, "seat0");
400dab
+}
400dab
+
400dab
 static void
400dab
 on_display_status_changed (GdmDisplay             *display,
400dab
                            GParamSpec             *arg1,
400dab
                            GdmLocalDisplayFactory *factory)
400dab
 {
400dab
         int              status;
400dab
         int              num;
400dab
         char            *seat_id = NULL;
400dab
         char            *session_type = NULL;
400dab
         char            *session_class = NULL;
400dab
         gboolean         is_initial = TRUE;
400dab
         gboolean         is_local = TRUE;
400dab
 
400dab
         num = -1;
400dab
         gdm_display_get_x11_display_number (display, &num, NULL);
400dab
 
400dab
         g_object_get (display,
400dab
                       "seat-id", &seat_id,
400dab
                       "is-initial", &is_initial,
400dab
                       "is-local", &is_local,
400dab
                       "session-type", &session_type,
400dab
                       "session-class", &session_class,
400dab
                       NULL);
400dab
 
400dab
         status = gdm_display_get_status (display);
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
400dab
         switch (status) {
400dab
         case GDM_DISPLAY_FINISHED:
400dab
                 /* remove the display number from factory->priv->used_display_numbers
400dab
@@ -359,60 +377,67 @@ on_display_status_changed (GdmDisplay             *display,
400dab
                 /* Create a new equivalent display if it was static */
400dab
                 if (is_local) {
400dab
 
400dab
                         factory->priv->num_failures++;
400dab
 
400dab
                         if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
400dab
                                 /* oh shit */
400dab
                                 g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
400dab
                         } else {
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
                                 if (g_strcmp0 (session_type, "wayland") == 0) {
400dab
                                         g_free (session_type);
400dab
                                         session_type = NULL;
400dab
 
400dab
                                         /* workaround logind race for now
400dab
                                          * bug 1643874
400dab
                                          */
400dab
                                         g_usleep (2 * G_USEC_PER_SEC);
400dab
                                 }
400dab
 
400dab
 #endif
400dab
                                 create_display (factory, seat_id, session_type, is_initial);
400dab
                         }
400dab
                 }
400dab
                 break;
400dab
         case GDM_DISPLAY_UNMANAGED:
400dab
                 break;
400dab
         case GDM_DISPLAY_PREPARED:
400dab
                 break;
400dab
         case GDM_DISPLAY_MANAGED:
400dab
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
+                g_signal_connect_object (display,
400dab
+                                         "notify::session-registered",
400dab
+                                         G_CALLBACK (on_session_registered_cb),
400dab
+                                         factory,
400dab
+                                         0);
400dab
+#endif
400dab
                 break;
400dab
         case GDM_DISPLAY_WAITING_TO_FINISH:
400dab
                 break;
400dab
         default:
400dab
                 g_assert_not_reached ();
400dab
                 break;
400dab
         }
400dab
 
400dab
         g_free (seat_id);
400dab
         g_free (session_type);
400dab
         g_free (session_class);
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 lookup_by_seat_id (const char *id,
400dab
                    GdmDisplay *display,
400dab
                    gpointer    user_data)
400dab
 {
400dab
         const char *looking_for = user_data;
400dab
         char *current;
400dab
         gboolean res;
400dab
 
400dab
         g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
400dab
 
400dab
         res = g_strcmp0 (current, looking_for) == 0;
400dab
 
400dab
         g_free(current);
400dab
 
400dab
         return res;
400dab
 }
400dab
@@ -587,100 +612,83 @@ on_seat_new (GDBusConnection *connection,
400dab
 }
400dab
 
400dab
 static void
400dab
 on_seat_removed (GDBusConnection *connection,
400dab
                  const gchar     *sender_name,
400dab
                  const gchar     *object_path,
400dab
                  const gchar     *interface_name,
400dab
                  const gchar     *signal_name,
400dab
                  GVariant        *parameters,
400dab
                  gpointer         user_data)
400dab
 {
400dab
         const char *seat;
400dab
 
400dab
         g_variant_get (parameters, "(&s&o)", &seat, NULL);
400dab
         delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
400dab
 }
400dab
 
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
 static gboolean
400dab
 lookup_by_session_id (const char *id,
400dab
                       GdmDisplay *display,
400dab
                       gpointer    user_data)
400dab
 {
400dab
         const char *looking_for = user_data;
400dab
         const char *current;
400dab
 
400dab
         current = gdm_display_get_session_id (display);
400dab
         return g_strcmp0 (current, looking_for) == 0;
400dab
 }
400dab
 
400dab
-static gboolean
400dab
-wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
400dab
-{
400dab
-        finish_waiting_displays_on_seat (factory, "seat0");
400dab
-        factory->priv->wait_to_finish_timeout_id = 0;
400dab
-        return G_SOURCE_REMOVE;
400dab
-}
400dab
-
400dab
 static void
400dab
 maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
400dab
                                   GdmDisplay             *display)
400dab
 {
400dab
         gboolean doing_initial_setup = FALSE;
400dab
 
400dab
         if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
400dab
                 g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
400dab
                 return;
400dab
         }
400dab
 
400dab
         g_object_get (G_OBJECT (display),
400dab
                       "doing-initial-setup", &doing_initial_setup,
400dab
                       NULL);
400dab
 
400dab
         /* we don't ever stop initial-setup implicitly */
400dab
         if (doing_initial_setup) {
400dab
                 g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
400dab
                 return;
400dab
         }
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
400dab
         g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
400dab
-
400dab
-        /* We stop the greeter after a timeout to avoid flicker */
400dab
-        if (factory->priv->wait_to_finish_timeout_id != 0)
400dab
-                g_source_remove (factory->priv->wait_to_finish_timeout_id);
400dab
-
400dab
-        factory->priv->wait_to_finish_timeout_id =
400dab
-                g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
400dab
-                                       (GSourceFunc)wait_to_finish_timeout,
400dab
-                                       factory);
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 on_vt_changed (GIOChannel    *source,
400dab
                GIOCondition   condition,
400dab
                GdmLocalDisplayFactory *factory)
400dab
 {
400dab
         GIOStatus status;
400dab
         g_autofree char *tty_of_active_vt = NULL;
400dab
         g_autofree char *login_session_id = NULL;
400dab
         g_autofree char *active_session_id = NULL;
400dab
         unsigned int previous_vt, new_vt;
400dab
         const char *session_type = NULL;
400dab
         int ret, n_returned;
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: received VT change event");
400dab
         g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
400dab
 
400dab
         if (condition & G_IO_PRI) {
400dab
                 g_autoptr (GError) error = NULL;
400dab
                 status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
400dab
 
400dab
                 if (error != NULL) {
400dab
                         g_warning ("could not read active VT from kernel: %s", error->message);
400dab
                 }
400dab
                 switch (status) {
400dab
                         case G_IO_STATUS_ERROR:
400dab
                             return G_SOURCE_REMOVE;
400dab
                         case G_IO_STATUS_EOF:
400dab
                             return G_SOURCE_REMOVE;
400dab
@@ -722,61 +730,60 @@ on_vt_changed (GIOChannel    *source,
400dab
         factory->priv->active_vt = new_vt;
400dab
 
400dab
         /* don't do anything at start up */
400dab
         if (previous_vt == 0) {
400dab
                 g_debug ("GdmLocalDisplayFactory: VT is %u at startup",
400dab
                          factory->priv->active_vt);
400dab
                 return G_SOURCE_CONTINUE;
400dab
         }
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: VT changed from %u to %u",
400dab
                  previous_vt, factory->priv->active_vt);
400dab
 
400dab
         /* if the old VT was running a wayland login screen kill it
400dab
          */
400dab
         if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
400dab
                 unsigned int login_window_vt;
400dab
 
400dab
                 ret = sd_session_get_vt (login_session_id, &login_window_vt);
400dab
                 if (ret == 0 && login_window_vt != 0) {
400dab
                         g_debug ("GdmLocalDisplayFactory: VT of login window is %u", login_window_vt);
400dab
                         if (login_window_vt == previous_vt) {
400dab
                                 GdmDisplayStore *store;
400dab
                                 GdmDisplay *display;
400dab
 
400dab
                                 g_debug ("GdmLocalDisplayFactory: VT switched from login window");
400dab
 
400dab
                                 store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
400dab
                                 display = gdm_display_store_find (store,
400dab
                                                                   lookup_by_session_id,
400dab
                                                                   (gpointer) login_session_id);
400dab
-
400dab
                                 if (display != NULL)
400dab
                                         maybe_stop_greeter_in_background (factory, display);
400dab
                         } else {
400dab
                                 g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
400dab
                         }
400dab
                 }
400dab
         }
400dab
 
400dab
         /* if user jumped back to initial vt and it's empty put a login screen
400dab
          * on it (unless a login screen is already running elsewhere, then
400dab
          * jump to that login screen)
400dab
          */
400dab
         if (factory->priv->active_vt != GDM_INITIAL_VT) {
400dab
                 g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
400dab
                 return G_SOURCE_CONTINUE;
400dab
         }
400dab
 
400dab
         if (gdm_local_display_factory_use_wayland ())
400dab
                 session_type = "wayland";
400dab
 
400dab
         g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
400dab
 
400dab
         create_display (factory, "seat0", session_type, TRUE);
400dab
 
400dab
         return G_SOURCE_CONTINUE;
400dab
 }
400dab
 #endif
400dab
 
400dab
 static void
400dab
 gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
400dab
@@ -805,64 +812,60 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
400dab
                                                                              g_object_unref);
400dab
 
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
         io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
400dab
 
400dab
         if (io_channel != NULL) {
400dab
                 factory->priv->active_vt_watch_id =
400dab
                         g_io_add_watch (io_channel,
400dab
                                         G_IO_PRI,
400dab
                                         (GIOFunc)
400dab
                                         on_vt_changed,
400dab
                                         factory);
400dab
         }
400dab
 #endif
400dab
 }
400dab
 
400dab
 static void
400dab
 gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
400dab
 {
400dab
         if (factory->priv->seat_new_id) {
400dab
                 g_dbus_connection_signal_unsubscribe (factory->priv->connection,
400dab
                                                       factory->priv->seat_new_id);
400dab
                 factory->priv->seat_new_id = 0;
400dab
         }
400dab
         if (factory->priv->seat_removed_id) {
400dab
                 g_dbus_connection_signal_unsubscribe (factory->priv->connection,
400dab
                                                       factory->priv->seat_removed_id);
400dab
                 factory->priv->seat_removed_id = 0;
400dab
         }
400dab
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
400dab
-        if (factory->priv->wait_to_finish_timeout_id != 0) {
400dab
-                g_source_remove (factory->priv->wait_to_finish_timeout_id);
400dab
-                factory->priv->wait_to_finish_timeout_id = 0;
400dab
-        }
400dab
         if (factory->priv->active_vt_watch_id) {
400dab
                 g_source_remove (factory->priv->active_vt_watch_id);
400dab
                 factory->priv->active_vt_watch_id = 0;
400dab
         }
400dab
 #endif
400dab
 }
400dab
 
400dab
 static void
400dab
 on_display_added (GdmDisplayStore        *display_store,
400dab
                   const char             *id,
400dab
                   GdmLocalDisplayFactory *factory)
400dab
 {
400dab
         GdmDisplay *display;
400dab
 
400dab
         display = gdm_display_store_lookup (display_store, id);
400dab
 
400dab
         if (display != NULL) {
400dab
                 g_signal_connect_object (display, "notify::status",
400dab
                                          G_CALLBACK (on_display_status_changed),
400dab
                                          factory,
400dab
                                          0);
400dab
 
400dab
                 g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 on_display_removed (GdmDisplayStore        *display_store,
400dab
                     GdmDisplay             *display,
400dab
                     GdmLocalDisplayFactory *factory)
400dab
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
400dab
index 5b76ba129..540a2534d 100644
400dab
--- a/daemon/gdm-session.c
400dab
+++ b/daemon/gdm-session.c
400dab
@@ -2849,132 +2849,139 @@ on_start_program_cb (GdmDBusWorker *worker,
400dab
 
400dab
         self = conversation->session;
400dab
         service_name = conversation->service_name;
400dab
 
400dab
         if (worked) {
400dab
                 self->priv->session_pid = pid;
400dab
                 self->priv->session_conversation = conversation;
400dab
 
400dab
                 g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'", pid);
400dab
                 g_signal_emit (self, signals[SESSION_STARTED], 0, service_name, pid);
400dab
         } else {
400dab
                 gdm_session_stop_conversation (self, service_name);
400dab
 
400dab
                 g_debug ("GdmSession: Emitting 'session-start-failed' signal");
400dab
                 g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, error->message);
400dab
         }
400dab
 }
400dab
 
400dab
 void
400dab
 gdm_session_start_session (GdmSession *self,
400dab
                            const char *service_name)
400dab
 {
400dab
         GdmSessionConversation *conversation;
400dab
         GdmSessionDisplayMode   display_mode;
400dab
         gboolean                is_x11 = TRUE;
400dab
         gboolean                run_launcher = FALSE;
400dab
         gboolean                allow_remote_connections = FALSE;
400dab
         gboolean                run_separate_bus = FALSE;
400dab
         char                   *command;
400dab
         char                   *program;
400dab
+        gboolean               register_session;
400dab
 
400dab
         g_return_if_fail (GDM_IS_SESSION (self));
400dab
         g_return_if_fail (self->priv->session_conversation == NULL);
400dab
 
400dab
         conversation = find_conversation_by_name (self, service_name);
400dab
 
400dab
         if (conversation == NULL) {
400dab
                 g_warning ("GdmSession: Tried to start session of "
400dab
                            "nonexistent conversation %s", service_name);
400dab
                 return;
400dab
         }
400dab
 
400dab
         stop_all_other_conversations (self, conversation, FALSE);
400dab
 
400dab
         display_mode = gdm_session_get_display_mode (self);
400dab
 
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
         is_x11 = g_strcmp0 (self->priv->session_type, "wayland") != 0;
400dab
 #endif
400dab
 
400dab
         if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED ||
400dab
             display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) {
400dab
                 run_launcher = TRUE;
400dab
         }
400dab
 
400dab
         if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0 && !run_launcher) {
400dab
                 run_separate_bus = TRUE;
400dab
         }
400dab
 
400dab
+        register_session = !gdm_session_session_registers (self);
400dab
+
400dab
         if (self->priv->selected_program == NULL) {
400dab
                 gboolean run_xsession_script;
400dab
 
400dab
                 command = get_session_command (self);
400dab
 
400dab
                 run_xsession_script = !gdm_session_bypasses_xsession (self);
400dab
 
400dab
                 if (self->priv->display_is_local) {
400dab
                         gboolean disallow_tcp = TRUE;
400dab
                         gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disallow_tcp);
400dab
                         allow_remote_connections = !disallow_tcp;
400dab
                 } else {
400dab
                         allow_remote_connections = TRUE;
400dab
                 }
400dab
 
400dab
                 if (run_launcher) {
400dab
                         if (is_x11) {
400dab
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s %s\"%s\"",
400dab
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"",
400dab
+                                                           register_session ? "--register-session " : "",
400dab
                                                            run_xsession_script? "--run-script " : "",
400dab
                                                            allow_remote_connections? "--allow-remote-connections " : "",
400dab
                                                            command);
400dab
                         } else {
400dab
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
400dab
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
400dab
+                                                           register_session ? "--register-session " : "",
400dab
                                                            command);
400dab
                         }
400dab
                 } else if (run_xsession_script) {
400dab
                     if (run_separate_bus) {
400dab
                             program = g_strdup_printf ("dbus-run-session -- " GDMCONFDIR "/Xsession \"%s\"", command);
400dab
                     } else {
400dab
                             program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
400dab
                     }
400dab
                 } else {
400dab
                         program = g_strdup (command);
400dab
                 }
400dab
 
400dab
                 g_free (command);
400dab
         } else {
400dab
                 if (run_launcher) {
400dab
                         if (is_x11) {
400dab
-                            program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"",
400dab
+                            program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"%s\"",
400dab
+                                                       register_session ? "--register-session " : "",
400dab
                                                        self->priv->selected_program);
400dab
                         } else {
400dab
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
400dab
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
400dab
+                                                           register_session ? "--register-session " : "",
400dab
                                                            self->priv->selected_program);
400dab
                         }
400dab
                 } else {
400dab
                         if (run_separate_bus) {
400dab
                                 program = g_strdup_printf ("dbus-run-session -- %s",
400dab
                                                            self->priv->selected_program);
400dab
                         } else {
400dab
                                 program = g_strdup (self->priv->selected_program);
400dab
                         }
400dab
                 }
400dab
         }
400dab
 
400dab
         set_up_session_environment (self);
400dab
         send_environment (self, conversation);
400dab
 
400dab
         gdm_dbus_worker_call_start_program (conversation->worker_proxy,
400dab
                                             program,
400dab
                                             conversation->worker_cancellable,
400dab
                                             (GAsyncReadyCallback) on_start_program_cb,
400dab
                                             conversation);
400dab
         g_free (program);
400dab
 }
400dab
 
400dab
 static void
400dab
 stop_all_conversations (GdmSession *self)
400dab
 {
400dab
         stop_all_other_conversations (self, NULL, TRUE);
400dab
 }
400dab
 
400dab
 static void
400dab
@@ -3199,60 +3206,92 @@ gdm_session_is_wayland_session (GdmSession *self)
400dab
                 }
400dab
 
400dab
                 if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
400dab
                         is_wayland_session = TRUE;
400dab
                 }
400dab
         }
400dab
 
400dab
 out:
400dab
         g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
400dab
 
400dab
         return is_wayland_session;
400dab
 }
400dab
 #endif
400dab
 
400dab
 static void
400dab
 update_session_type (GdmSession *self)
400dab
 {
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
         gboolean is_wayland_session = FALSE;
400dab
 
400dab
         is_wayland_session = gdm_session_is_wayland_session (self);
400dab
 
400dab
         if (is_wayland_session) {
400dab
                 set_session_type (self, "wayland");
400dab
         } else {
400dab
                 set_session_type (self, NULL);
400dab
         }
400dab
 #endif
400dab
 }
400dab
 
400dab
+gboolean
400dab
+gdm_session_session_registers (GdmSession *self)
400dab
+{
400dab
+        g_autoptr(GError) error = NULL;
400dab
+        g_autoptr(GKeyFile) key_file = NULL;
400dab
+        gboolean session_registers = FALSE;
400dab
+        g_autofree char *filename = NULL;
400dab
+
400dab
+        g_return_val_if_fail (self != NULL, FALSE);
400dab
+        g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
400dab
+
400dab
+        filename = get_session_filename (self);
400dab
+
400dab
+        key_file = load_key_file_for_file (self, filename, NULL, NULL);
400dab
+
400dab
+        session_registers = g_key_file_get_boolean (key_file,
400dab
+                                                    G_KEY_FILE_DESKTOP_GROUP,
400dab
+                                                    "X-GDM-SessionRegisters",
400dab
+                                                    &error);
400dab
+        if (!session_registers &&
400dab
+            error != NULL &&
400dab
+            !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
400dab
+                g_warning ("GdmSession: Couldn't read session file '%s'", filename);
400dab
+                return FALSE;
400dab
+        }
400dab
+
400dab
+        g_debug ("GdmSession: '%s' %s self", filename,
400dab
+                 session_registers ? "registers" : "does not register");
400dab
+
400dab
+        return session_registers;
400dab
+}
400dab
+
400dab
 gboolean
400dab
 gdm_session_bypasses_xsession (GdmSession *self)
400dab
 {
400dab
         GError     *error;
400dab
         GKeyFile   *key_file;
400dab
         gboolean    res;
400dab
         gboolean    bypasses_xsession = FALSE;
400dab
         char       *filename = NULL;
400dab
 
400dab
         g_return_val_if_fail (self != NULL, FALSE);
400dab
         g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
400dab
 
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
         if (gdm_session_is_wayland_session (self)) {
400dab
                 bypasses_xsession = TRUE;
400dab
                 goto out;
400dab
         }
400dab
 #endif
400dab
 
400dab
         filename = get_session_filename (self);
400dab
 
400dab
         key_file = load_key_file_for_file (self, filename, "x11",  NULL);
400dab
 
400dab
         error = NULL;
400dab
         res = g_key_file_has_key (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", NULL);
400dab
         if (!res) {
400dab
                 goto out;
400dab
         } else {
400dab
                 bypasses_xsession = g_key_file_get_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, "X-GDM-BypassXsession", &error);
400dab
                 if (error) {
400dab
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
400dab
index a22c09543..682d2c99f 100644
400dab
--- a/daemon/gdm-session.h
400dab
+++ b/daemon/gdm-session.h
400dab
@@ -108,60 +108,61 @@ typedef struct
400dab
         void (* conversation_started)        (GdmSession   *session,
400dab
                                               const char   *service_name);
400dab
         void (* conversation_stopped)        (GdmSession   *session,
400dab
                                               const char   *service_name);
400dab
         void (* setup_complete)              (GdmSession   *session,
400dab
                                               const char   *service_name);
400dab
 } GdmSessionClass;
400dab
 
400dab
 GType            gdm_session_get_type                 (void);
400dab
 
400dab
 GdmSession      *gdm_session_new                      (GdmSessionVerificationMode verification_mode,
400dab
                                                        uid_t         allowed_user,
400dab
                                                        const char   *display_name,
400dab
                                                        const char   *display_hostname,
400dab
                                                        const char   *display_device,
400dab
                                                        const char   *display_seat_id,
400dab
                                                        const char   *display_x11_authority_file,
400dab
                                                        gboolean      display_is_local,
400dab
                                                        const char * const *environment);
400dab
 uid_t             gdm_session_get_allowed_user       (GdmSession     *session);
400dab
 void              gdm_session_start_reauthentication (GdmSession *session,
400dab
                                                       GPid        pid_of_caller,
400dab
                                                       uid_t       uid_of_caller);
400dab
 
400dab
 const char       *gdm_session_get_server_address          (GdmSession     *session);
400dab
 const char       *gdm_session_get_username                (GdmSession     *session);
400dab
 const char       *gdm_session_get_display_device          (GdmSession     *session);
400dab
 const char       *gdm_session_get_display_seat_id         (GdmSession     *session);
400dab
 const char       *gdm_session_get_session_id              (GdmSession     *session);
400dab
 gboolean          gdm_session_bypasses_xsession           (GdmSession     *session);
400dab
+gboolean          gdm_session_session_registers           (GdmSession     *session);
400dab
 GdmSessionDisplayMode gdm_session_get_display_mode  (GdmSession     *session);
400dab
 
400dab
 #ifdef ENABLE_WAYLAND_SUPPORT
400dab
 void              gdm_session_set_ignore_wayland          (GdmSession *session,
400dab
                                                            gboolean    ignore_wayland);
400dab
 #endif
400dab
 gboolean          gdm_session_start_conversation          (GdmSession *session,
400dab
                                                            const char *service_name);
400dab
 void              gdm_session_stop_conversation           (GdmSession *session,
400dab
                                                            const char *service_name);
400dab
 const char       *gdm_session_get_conversation_session_id (GdmSession *session,
400dab
                                                            const char *service_name);
400dab
 void              gdm_session_setup                       (GdmSession *session,
400dab
                                                            const char *service_name);
400dab
 void              gdm_session_setup_for_user              (GdmSession *session,
400dab
                                                            const char *service_name,
400dab
                                                            const char *username);
400dab
 void              gdm_session_setup_for_program           (GdmSession *session,
400dab
                                                            const char *service_name,
400dab
                                                            const char *username,
400dab
                                                            const char *log_file);
400dab
 void              gdm_session_set_environment_variable    (GdmSession *session,
400dab
                                                            const char *key,
400dab
                                                            const char *value);
400dab
 void              gdm_session_send_environment            (GdmSession *self,
400dab
                                                            const char *service_name);
400dab
 void              gdm_session_reset                       (GdmSession *session);
400dab
 void              gdm_session_cancel                      (GdmSession *session);
400dab
 void              gdm_session_authenticate                (GdmSession *session,
400dab
                                                            const char *service_name);
400dab
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
400dab
index 94f49e19c..35679b194 100644
400dab
--- a/daemon/gdm-wayland-session.c
400dab
+++ b/daemon/gdm-wayland-session.c
400dab
@@ -18,68 +18,71 @@
400dab
  * 02110-1301, USA.
400dab
  */
400dab
 #include "config.h"
400dab
 
400dab
 #include <locale.h>
400dab
 #include <sysexits.h>
400dab
 
400dab
 #include "gdm-common.h"
400dab
 #include "gdm-settings-direct.h"
400dab
 #include "gdm-settings-keys.h"
400dab
 #include "gdm-log.h"
400dab
 
400dab
 #include "gdm-manager-glue.h"
400dab
 
400dab
 #include <glib/gi18n.h>
400dab
 #include <glib/gstdio.h>
400dab
 #include <glib-unix.h>
400dab
 #include <glib.h>
400dab
 
400dab
 #include <gio/gunixinputstream.h>
400dab
 
400dab
 #define BUS_ADDRESS_FILENO (STDERR_FILENO + 1)
400dab
 
400dab
 typedef struct
400dab
 {
400dab
         GdmSettings  *settings;
400dab
         GCancellable *cancellable;
400dab
 
400dab
         GSubprocess     *bus_subprocess;
400dab
         GDBusConnection *bus_connection;
400dab
+        GdmDBusManager  *display_manager_proxy;
400dab
         char            *bus_address;
400dab
 
400dab
         char           **environment;
400dab
 
400dab
         GSubprocess  *session_subprocess;
400dab
         char         *session_command;
400dab
         int           session_exit_status;
400dab
 
400dab
+        guint         register_session_id;
400dab
+
400dab
         GMainLoop    *main_loop;
400dab
 
400dab
         guint32       debug_enabled : 1;
400dab
 } State;
400dab
 
400dab
 static void
400dab
 on_bus_finished (GSubprocess  *subprocess,
400dab
                  GAsyncResult *result,
400dab
                  State        *state)
400dab
 {
400dab
         gboolean cancelled;
400dab
 
400dab
         cancelled = !g_subprocess_wait_finish (subprocess, result, NULL);
400dab
 
400dab
         if (cancelled) {
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         if (g_subprocess_get_if_exited (subprocess)) {
400dab
                 int exit_status;
400dab
 
400dab
                 exit_status = g_subprocess_get_exit_status (subprocess);
400dab
 
400dab
                 g_debug ("message bus exited with status %d", exit_status);
400dab
         } else {
400dab
                 int signal_number;
400dab
 
400dab
                 signal_number = g_subprocess_get_term_sig (subprocess);
400dab
                 g_debug ("message bus was killed with status %d", signal_number);
400dab
         }
400dab
@@ -358,140 +361,170 @@ out:
400dab
 }
400dab
 
400dab
 static void
400dab
 signal_subprocesses (State *state)
400dab
 {
400dab
         if (state->session_subprocess != NULL) {
400dab
                 g_subprocess_send_signal (state->session_subprocess, SIGTERM);
400dab
         }
400dab
 
400dab
         if (state->bus_subprocess != NULL) {
400dab
                 g_subprocess_send_signal (state->bus_subprocess, SIGTERM);
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 wait_on_subprocesses (State *state)
400dab
 {
400dab
         if (state->bus_subprocess != NULL) {
400dab
                 g_subprocess_wait (state->bus_subprocess, NULL, NULL);
400dab
         }
400dab
 
400dab
         if (state->session_subprocess != NULL) {
400dab
                 g_subprocess_wait (state->session_subprocess, NULL, NULL);
400dab
         }
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 register_display (State        *state,
400dab
                   GCancellable *cancellable)
400dab
 {
400dab
-        GdmDBusManager  *manager = NULL;
400dab
         GError          *error = NULL;
400dab
         gboolean         registered = FALSE;
400dab
         GVariantBuilder  details;
400dab
 
400dab
-        manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
400dab
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
400dab
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
400dab
-                                                           "org.gnome.DisplayManager",
400dab
-                                                           "/org/gnome/DisplayManager/Manager",
400dab
-                                                           cancellable,
400dab
-                                                           &error);
400dab
-
400dab
-        if (!manager) {
400dab
-                g_debug ("could not contact display manager: %s", error->message);
400dab
-                g_error_free (error);
400dab
-                goto out;
400dab
-        }
400dab
-
400dab
         g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
400dab
         g_variant_builder_add (&details, "{ss}", "session-type", "wayland");
400dab
 
400dab
-        registered = gdm_dbus_manager_call_register_display_sync (manager,
400dab
+        registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
400dab
                                                                   g_variant_builder_end (&details),
400dab
                                                                   cancellable,
400dab
                                                                   &error);
400dab
         if (error != NULL) {
400dab
                 g_debug ("Could not register display: %s", error->message);
400dab
                 g_error_free (error);
400dab
         }
400dab
 
400dab
-out:
400dab
-        g_clear_object (&manager);
400dab
         return registered;
400dab
 }
400dab
 
400dab
 static void
400dab
 init_state (State **state)
400dab
 {
400dab
         static State state_allocation;
400dab
 
400dab
         *state = &state_allocation;
400dab
 }
400dab
 
400dab
 static void
400dab
 clear_state (State **out_state)
400dab
 {
400dab
         State *state = *out_state;
400dab
 
400dab
         g_clear_object (&state->cancellable);
400dab
         g_clear_object (&state->bus_connection);
400dab
         g_clear_object (&state->session_subprocess);
400dab
         g_clear_pointer (&state->environment, g_strfreev);
400dab
         g_clear_pointer (&state->main_loop, g_main_loop_unref);
400dab
+        g_clear_handle_id (&state->register_session_id, g_source_remove);
400dab
         *out_state = NULL;
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 on_sigterm (State *state)
400dab
 {
400dab
         g_cancellable_cancel (state->cancellable);
400dab
 
400dab
         if (g_main_loop_is_running (state->main_loop)) {
400dab
                 g_main_loop_quit (state->main_loop);
400dab
         }
400dab
 
400dab
         return G_SOURCE_CONTINUE;
400dab
 }
400dab
 
400dab
+static gboolean
400dab
+register_session_timeout_cb (gpointer user_data)
400dab
+{
400dab
+        State *state;
400dab
+        GError *error = NULL;
400dab
+
400dab
+        state = (State *) user_data;
400dab
+
400dab
+        gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
400dab
+                                                     g_variant_new ("a{sv}", NULL),
400dab
+                                                     state->cancellable,
400dab
+                                                     &error);
400dab
+
400dab
+        if (error != NULL) {
400dab
+                g_warning ("Could not register session: %s", error->message);
400dab
+                g_error_free (error);
400dab
+        }
400dab
+
400dab
+        return G_SOURCE_REMOVE;
400dab
+}
400dab
+
400dab
+static gboolean
400dab
+connect_to_display_manager (State *state)
400dab
+{
400dab
+        g_autoptr (GError) error = NULL;
400dab
+
400dab
+        state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
400dab
+                G_BUS_TYPE_SYSTEM,
400dab
+                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
400dab
+                "org.gnome.DisplayManager",
400dab
+                "/org/gnome/DisplayManager/Manager",
400dab
+                state->cancellable,
400dab
+                &error);
400dab
+
400dab
+        if (state->display_manager_proxy == NULL) {
400dab
+                g_printerr ("gdm-wayland-session: could not contact display manager: %s\n",
400dab
+                            error->message);
400dab
+                return FALSE;
400dab
+        }
400dab
+
400dab
+        return TRUE;
400dab
+}
400dab
+
400dab
 int
400dab
 main (int    argc,
400dab
       char **argv)
400dab
 {
400dab
         State           *state = NULL;
400dab
         GOptionContext  *context = NULL;
400dab
         static char    **args = NULL;
400dab
         gboolean         debug = FALSE;
400dab
         gboolean         ret;
400dab
         int              exit_status = EX_OK;
400dab
+        static gboolean  register_session = FALSE;
400dab
+
400dab
         static GOptionEntry entries []   = {
400dab
+                { "register-session", 0, 0, G_OPTION_ARG_NONE, &register_session, "Register session after a delay", NULL },
400dab
                 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
400dab
                 { NULL }
400dab
         };
400dab
 
400dab
         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
400dab
         textdomain (GETTEXT_PACKAGE);
400dab
         setlocale (LC_ALL, "");
400dab
 
400dab
         gdm_log_init ();
400dab
 
400dab
         context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
400dab
         g_option_context_add_main_entries (context, entries, NULL);
400dab
 
400dab
         g_option_context_parse (context, &argc, &argv, NULL);
400dab
         g_option_context_free (context);
400dab
 
400dab
         if (args == NULL || args[0] == NULL || args[1] != NULL) {
400dab
                 g_warning ("gdm-wayland-session takes one argument (the session)");
400dab
                 exit_status = EX_USAGE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         init_state (&state);
400dab
 
400dab
         state->session_command = args[0];
400dab
 
400dab
         state->settings = gdm_settings_new ();
400dab
         ret = gdm_settings_direct_init (state->settings, DATADIR "/gdm/gdm.schemas", "/");
400dab
 
400dab
         if (!ret) {
400dab
@@ -501,55 +534,67 @@ main (int    argc,
400dab
         }
400dab
 
400dab
         gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
400dab
         state->debug_enabled = debug;
400dab
 
400dab
         gdm_log_set_debug (debug);
400dab
 
400dab
         state->main_loop = g_main_loop_new (NULL, FALSE);
400dab
         state->cancellable = g_cancellable_new ();
400dab
 
400dab
         g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
400dab
 
400dab
         ret = spawn_bus (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to run session message bus\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         import_environment (state, state->cancellable);
400dab
 
400dab
         ret = spawn_session (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to run session\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
+        if (!connect_to_display_manager (state))
400dab
+                goto out;
400dab
+
400dab
         ret = register_display (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to register display with display manager\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
+        if (register_session) {
400dab
+                g_debug ("gdm-wayland-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
400dab
+                state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
400dab
+                                                                    register_session_timeout_cb,
400dab
+                                                                    state);
400dab
+        } else {
400dab
+                g_debug ("gdm-wayland-session: Session will register itself");
400dab
+        }
400dab
+
400dab
         g_main_loop_run (state->main_loop);
400dab
 
400dab
         /* Only use exit status of session if we're here because it exit */
400dab
 
400dab
         if (state->session_subprocess == NULL) {
400dab
                 exit_status = state->session_exit_status;
400dab
         }
400dab
 
400dab
 out:
400dab
         if (state != NULL) {
400dab
                 signal_subprocesses (state);
400dab
                 wait_on_subprocesses (state);
400dab
                 clear_state (&state);
400dab
         }
400dab
 
400dab
         return exit_status;
400dab
 }
400dab
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
400dab
index d8e3c7d53..f0082fdc6 100644
400dab
--- a/daemon/gdm-x-session.c
400dab
+++ b/daemon/gdm-x-session.c
400dab
@@ -24,68 +24,71 @@
400dab
 
400dab
 #include "gdm-common.h"
400dab
 #include "gdm-settings-direct.h"
400dab
 #include "gdm-settings-keys.h"
400dab
 #include "gdm-log.h"
400dab
 
400dab
 #include "gdm-manager-glue.h"
400dab
 
400dab
 #include <glib/gi18n.h>
400dab
 #include <glib/gstdio.h>
400dab
 #include <glib-unix.h>
400dab
 #include <glib.h>
400dab
 #include <gio/gunixinputstream.h>
400dab
 #include <glib-unix.h>
400dab
 #include <X11/Xauth.h>
400dab
 
400dab
 #define DISPLAY_FILENO (STDERR_FILENO + 1)
400dab
 #define BUS_ADDRESS_FILENO (DISPLAY_FILENO + 1)
400dab
 
400dab
 typedef struct
400dab
 {
400dab
         GdmSettings  *settings;
400dab
         GCancellable *cancellable;
400dab
 
400dab
         GSubprocess  *x_subprocess;
400dab
         char         *auth_file;
400dab
         char         *display_name;
400dab
 
400dab
         GSubprocess     *bus_subprocess;
400dab
         GDBusConnection *bus_connection;
400dab
+        GdmDBusManager  *display_manager_proxy;
400dab
         char            *bus_address;
400dab
 
400dab
         char           **environment;
400dab
 
400dab
         GSubprocess  *session_subprocess;
400dab
         char         *session_command;
400dab
         int           session_exit_status;
400dab
 
400dab
+        guint         register_session_id;
400dab
+
400dab
         GMainLoop    *main_loop;
400dab
 
400dab
         guint32       debug_enabled : 1;
400dab
 } State;
400dab
 
400dab
 static FILE *
400dab
 create_auth_file (char **filename)
400dab
 {
400dab
         char *auth_dir = NULL;
400dab
         char *auth_file = NULL;
400dab
         int fd;
400dab
         FILE *fp = NULL;
400dab
 
400dab
         auth_dir = g_build_filename (g_get_user_runtime_dir (),
400dab
                                      "gdm",
400dab
                                      NULL);
400dab
 
400dab
         g_mkdir_with_parents (auth_dir, 0711);
400dab
         auth_file = g_build_filename (auth_dir, "Xauthority", NULL);
400dab
         g_clear_pointer (&auth_dir, g_free);
400dab
 
400dab
         fd = g_open (auth_file, O_RDWR | O_CREAT | O_TRUNC, 0700);
400dab
 
400dab
         if (fd < 0) {
400dab
                 g_debug ("could not open %s to store auth cookie: %m",
400dab
                          auth_file);
400dab
                 g_clear_pointer (&auth_file, g_free);
400dab
                 goto out;
400dab
         }
400dab
 
400dab
@@ -711,148 +714,178 @@ signal_subprocesses (State *state)
400dab
 
400dab
         if (state->bus_subprocess != NULL) {
400dab
                 g_subprocess_send_signal (state->bus_subprocess, SIGTERM);
400dab
         }
400dab
 
400dab
         if (state->x_subprocess != NULL) {
400dab
                 g_subprocess_send_signal (state->x_subprocess, SIGTERM);
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 wait_on_subprocesses (State *state)
400dab
 {
400dab
         if (state->x_subprocess != NULL) {
400dab
                 g_subprocess_wait (state->x_subprocess, NULL, NULL);
400dab
         }
400dab
 
400dab
         if (state->bus_subprocess != NULL) {
400dab
                 g_subprocess_wait (state->bus_subprocess, NULL, NULL);
400dab
         }
400dab
 
400dab
         if (state->session_subprocess != NULL) {
400dab
                 g_subprocess_wait (state->session_subprocess, NULL, NULL);
400dab
         }
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 register_display (State        *state,
400dab
                   GCancellable *cancellable)
400dab
 {
400dab
-        GdmDBusManager  *manager = NULL;
400dab
         GError          *error = NULL;
400dab
         gboolean         registered = FALSE;
400dab
         GVariantBuilder  details;
400dab
 
400dab
-        manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
400dab
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
400dab
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
400dab
-                                                           "org.gnome.DisplayManager",
400dab
-                                                           "/org/gnome/DisplayManager/Manager",
400dab
-                                                           cancellable,
400dab
-                                                           &error);
400dab
-
400dab
-        if (!manager) {
400dab
-                g_debug ("could not contact display manager: %s", error->message);
400dab
-                g_error_free (error);
400dab
-                goto out;
400dab
-        }
400dab
-
400dab
         g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
400dab
         g_variant_builder_add (&details, "{ss}", "session-type", "x11");
400dab
         g_variant_builder_add (&details, "{ss}", "x11-display-name", state->display_name);
400dab
 
400dab
-        registered = gdm_dbus_manager_call_register_display_sync (manager,
400dab
+        registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
400dab
                                                                   g_variant_builder_end (&details),
400dab
                                                                   cancellable,
400dab
                                                                   &error);
400dab
         if (error != NULL) {
400dab
                 g_debug ("Could not register display: %s", error->message);
400dab
                 g_error_free (error);
400dab
         }
400dab
 
400dab
-out:
400dab
-        g_clear_object (&manager);
400dab
         return registered;
400dab
 }
400dab
 
400dab
 static void
400dab
 init_state (State **state)
400dab
 {
400dab
         static State state_allocation;
400dab
 
400dab
         *state = &state_allocation;
400dab
 }
400dab
 
400dab
 static void
400dab
 clear_state (State **out_state)
400dab
 {
400dab
         State *state = *out_state;
400dab
 
400dab
         g_clear_object (&state->cancellable);
400dab
         g_clear_object (&state->bus_connection);
400dab
         g_clear_object (&state->session_subprocess);
400dab
         g_clear_object (&state->x_subprocess);
400dab
         g_clear_pointer (&state->environment, g_strfreev);
400dab
         g_clear_pointer (&state->auth_file, g_free);
400dab
         g_clear_pointer (&state->display_name, g_free);
400dab
         g_clear_pointer (&state->main_loop, g_main_loop_unref);
400dab
+        g_clear_handle_id (&state->register_session_id, g_source_remove);
400dab
         *out_state = NULL;
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 on_sigterm (State *state)
400dab
 {
400dab
         g_cancellable_cancel (state->cancellable);
400dab
 
400dab
         if (g_main_loop_is_running (state->main_loop)) {
400dab
                 g_main_loop_quit (state->main_loop);
400dab
         }
400dab
 
400dab
         return G_SOURCE_CONTINUE;
400dab
 }
400dab
 
400dab
+static gboolean
400dab
+register_session_timeout_cb (gpointer user_data)
400dab
+{
400dab
+        State *state;
400dab
+        GError *error = NULL;
400dab
+
400dab
+        state = (State *) user_data;
400dab
+
400dab
+        gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
400dab
+                                                     g_variant_new ("a{sv}", NULL),
400dab
+                                                     state->cancellable,
400dab
+                                                     &error);
400dab
+
400dab
+        if (error != NULL) {
400dab
+                g_warning ("Could not register session: %s", error->message);
400dab
+                g_error_free (error);
400dab
+        }
400dab
+
400dab
+        return G_SOURCE_REMOVE;
400dab
+}
400dab
+
400dab
+static gboolean
400dab
+connect_to_display_manager (State *state)
400dab
+{
400dab
+        g_autoptr (GError) error = NULL;
400dab
+
400dab
+        state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
400dab
+                G_BUS_TYPE_SYSTEM,
400dab
+                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
400dab
+                "org.gnome.DisplayManager",
400dab
+                "/org/gnome/DisplayManager/Manager",
400dab
+                state->cancellable,
400dab
+                &error);
400dab
+
400dab
+        if (state->display_manager_proxy == NULL) {
400dab
+                g_printerr ("gdm-x-session: could not contact display manager: %s\n",
400dab
+                            error->message);
400dab
+                return FALSE;
400dab
+        }
400dab
+
400dab
+        return TRUE;
400dab
+}
400dab
+
400dab
 int
400dab
 main (int    argc,
400dab
       char **argv)
400dab
 {
400dab
         State           *state = NULL;
400dab
         GOptionContext  *context = NULL;
400dab
         static char    **args = NULL;
400dab
         static gboolean  run_script = FALSE;
400dab
         static gboolean  allow_remote_connections = FALSE;
400dab
         gboolean         debug = FALSE;
400dab
         gboolean         ret;
400dab
         int              exit_status = EX_OK;
400dab
+        static gboolean  register_session = FALSE;
400dab
+
400dab
         static GOptionEntry entries []   = {
400dab
                 { "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
400dab
                 { "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
400dab
+                { "register-session", 0, 0, G_OPTION_ARG_NONE, &register_session, "Register session after a delay", NULL },
400dab
                 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
400dab
                 { NULL }
400dab
         };
400dab
 
400dab
         bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
400dab
         textdomain (GETTEXT_PACKAGE);
400dab
         setlocale (LC_ALL, "");
400dab
 
400dab
         gdm_log_init ();
400dab
 
400dab
         context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
400dab
         g_option_context_add_main_entries (context, entries, NULL);
400dab
 
400dab
         g_option_context_parse (context, &argc, &argv, NULL);
400dab
         g_option_context_free (context);
400dab
 
400dab
         if (args == NULL || args[0] == NULL || args[1] != NULL) {
400dab
                 g_warning ("gdm-x-session takes one argument (the session)");
400dab
                 exit_status = EX_USAGE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         init_state (&state);
400dab
 
400dab
         state->session_command = args[0];
400dab
 
400dab
         state->settings = gdm_settings_new ();
400dab
         ret = gdm_settings_direct_init (state->settings, DATADIR "/gdm/gdm.schemas", "/");
400dab
 
400dab
         if (!ret) {
400dab
@@ -870,63 +903,75 @@ main (int    argc,
400dab
         state->cancellable = g_cancellable_new ();
400dab
 
400dab
         g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
400dab
 
400dab
         ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to run X server\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         ret = spawn_bus (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to run session message bus\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         import_environment (state, state->cancellable);
400dab
 
400dab
         ret = update_bus_environment (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to update bus environment\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
+        if (!connect_to_display_manager (state))
400dab
+                goto out;
400dab
+
400dab
         ret = register_display (state, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to register display with display manager\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
         ret = spawn_session (state, run_script, state->cancellable);
400dab
 
400dab
         if (!ret) {
400dab
                 g_printerr ("Unable to run session\n");
400dab
                 exit_status = EX_SOFTWARE;
400dab
                 goto out;
400dab
         }
400dab
 
400dab
+        if (register_session) {
400dab
+                g_debug ("gdm-x-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
400dab
+                state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
400dab
+                                                                    register_session_timeout_cb,
400dab
+                                                                    state);
400dab
+        } else {
400dab
+                g_debug ("gdm-x-session: Session will register itself");
400dab
+        }
400dab
+
400dab
         g_main_loop_run (state->main_loop);
400dab
 
400dab
         /* Only use exit status of session if we're here because it exit */
400dab
 
400dab
         if (state->session_subprocess == NULL) {
400dab
                 exit_status = state->session_exit_status;
400dab
         }
400dab
 
400dab
 out:
400dab
         if (state != NULL) {
400dab
                 signal_subprocesses (state);
400dab
                 wait_on_subprocesses (state);
400dab
                 clear_state (&state);
400dab
         }
400dab
 
400dab
         return exit_status;
400dab
 }
400dab
-- 
400dab
2.27.0
400dab