Blame SOURCES/0006-manager-ensure-factories-are-stopped-at-shutdown.patch

c4edd0
From 86cff2e65b3d1f1186b378d7b5818531ff6b1d94 Mon Sep 17 00:00:00 2001
c4edd0
From: Ray Strode <rstrode@redhat.com>
c4edd0
Date: Fri, 25 Oct 2019 09:27:15 -0400
c4edd0
Subject: [PATCH 6/7] manager: ensure factories are stopped at shutdown
c4edd0
c4edd0
GDM doesn't currently stop it's display handling logic when it's
c4edd0
asked to shutdown.
c4edd0
c4edd0
That can lead to X servers attempting to start themsevles as GDM
c4edd0
is tearing itself down.
c4edd0
c4edd0
This commit addresses the problem adding some stop calls to the
c4edd0
code.
c4edd0
---
c4edd0
 daemon/gdm-local-display-factory.c | 15 +++++++++++++--
c4edd0
 daemon/gdm-manager.c               |  5 +++++
c4edd0
 2 files changed, 18 insertions(+), 2 deletions(-)
c4edd0
c4edd0
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
c4edd0
index 1c7daeb14..ad128d2c8 100644
c4edd0
--- a/daemon/gdm-local-display-factory.c
c4edd0
+++ b/daemon/gdm-local-display-factory.c
c4edd0
@@ -34,60 +34,62 @@
c4edd0
 #include "gdm-manager.h"
c4edd0
 #include "gdm-display-factory.h"
c4edd0
 #include "gdm-local-display-factory.h"
c4edd0
 #include "gdm-local-display-factory-glue.h"
c4edd0
 
c4edd0
 #include "gdm-settings-keys.h"
c4edd0
 #include "gdm-settings-direct.h"
c4edd0
 #include "gdm-display-store.h"
c4edd0
 #include "gdm-local-display.h"
c4edd0
 #include "gdm-legacy-display.h"
c4edd0
 
c4edd0
 #define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
c4edd0
 
c4edd0
 #define GDM_DBUS_PATH                       "/org/gnome/DisplayManager"
c4edd0
 #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
c4edd0
 #define GDM_MANAGER_DBUS_NAME               "org.gnome.DisplayManager.LocalDisplayFactory"
c4edd0
 
c4edd0
 #define MAX_DISPLAY_FAILURES 5
c4edd0
 
c4edd0
 struct GdmLocalDisplayFactoryPrivate
c4edd0
 {
c4edd0
         GdmDBusLocalDisplayFactory *skeleton;
c4edd0
         GDBusConnection *connection;
c4edd0
         GHashTable      *used_display_numbers;
c4edd0
 
c4edd0
         /* FIXME: this needs to be per seat? */
c4edd0
         guint            num_failures;
c4edd0
 
c4edd0
         guint            seat_new_id;
c4edd0
         guint            seat_removed_id;
c4edd0
+
c4edd0
+        gboolean         started;
c4edd0
 };
c4edd0
 
c4edd0
 enum {
c4edd0
         PROP_0,
c4edd0
 };
c4edd0
 
c4edd0
 static void     gdm_local_display_factory_class_init    (GdmLocalDisplayFactoryClass *klass);
c4edd0
 static void     gdm_local_display_factory_init          (GdmLocalDisplayFactory      *factory);
c4edd0
 static void     gdm_local_display_factory_finalize      (GObject                     *object);
c4edd0
 
c4edd0
 static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory,
c4edd0
                                                          const char                  *seat_id,
c4edd0
                                                          const char                  *session_type,
c4edd0
                                                          gboolean                    initial_display);
c4edd0
 
c4edd0
 static void     on_display_status_changed               (GdmDisplay                  *display,
c4edd0
                                                          GParamSpec                  *arg1,
c4edd0
                                                          GdmLocalDisplayFactory      *factory);
c4edd0
 
c4edd0
 static gboolean gdm_local_display_factory_sync_seats    (GdmLocalDisplayFactory *factory);
c4edd0
 static gpointer local_display_factory_object = NULL;
c4edd0
 
c4edd0
 G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
c4edd0
 
c4edd0
 GQuark
c4edd0
 gdm_local_display_factory_error_quark (void)
c4edd0
 {
c4edd0
         static GQuark ret = 0;
c4edd0
         if (ret == 0) {
c4edd0
                 ret = g_quark_from_static_string ("gdm_local_display_factory_error");
c4edd0
@@ -233,60 +235,63 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
c4edd0
         }
c4edd0
 
c4edd0
         if (! gdm_display_get_id (display, id, NULL)) {
c4edd0
                 display = NULL;
c4edd0
                 goto out;
c4edd0
         }
c4edd0
 
c4edd0
         ret = TRUE;
c4edd0
  out:
c4edd0
         /* ref either held by store or not at all */
c4edd0
         g_object_unref (display);
c4edd0
 
c4edd0
         return ret;
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 on_display_status_changed (GdmDisplay             *display,
c4edd0
                            GParamSpec             *arg1,
c4edd0
                            GdmLocalDisplayFactory *factory)
c4edd0
 {
c4edd0
         int              status;
c4edd0
         int              num;
c4edd0
         char            *seat_id = NULL;
c4edd0
         char            *session_id = NULL;
c4edd0
         char            *session_type = NULL;
c4edd0
         char            *session_class = NULL;
c4edd0
         gboolean         is_initial = TRUE;
c4edd0
         gboolean         is_local = TRUE;
c4edd0
         int              ret;
c4edd0
 
c4edd0
+        if (!factory->priv->started)
c4edd0
+                return;
c4edd0
+
c4edd0
         num = -1;
c4edd0
         gdm_display_get_x11_display_number (display, &num, NULL);
c4edd0
 
c4edd0
         g_object_get (display,
c4edd0
                       "seat-id", &seat_id,
c4edd0
                       "session-id", &session_id,
c4edd0
                       "is-initial", &is_initial,
c4edd0
                       "is-local", &is_local,
c4edd0
                       "session-type", &session_type,
c4edd0
                       "session-class", &session_class,
c4edd0
                       NULL);
c4edd0
 
c4edd0
         status = gdm_display_get_status (display);
c4edd0
 
c4edd0
         g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
c4edd0
         switch (status) {
c4edd0
         case GDM_DISPLAY_FINISHED:
c4edd0
                 /* remove the display number from factory->priv->used_display_numbers
c4edd0
                    so that it may be reused */
c4edd0
                 if (num != -1) {
c4edd0
                         g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
c4edd0
                 }
c4edd0
                 gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
c4edd0
 
c4edd0
                 /* if this is a local display, recreate the display so
c4edd0
                  * a new login screen comes up if one is missing.
c4edd0
                  */
c4edd0
                 if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
c4edd0
                         g_autofree char *active_session = NULL;
c4edd0
 
c4edd0
@@ -739,82 +744,88 @@ on_display_removed (GdmDisplayStore        *display_store,
c4edd0
         if (display != NULL) {
c4edd0
                 g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
c4edd0
                 g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
c4edd0
 
c4edd0
         }
c4edd0
 }
c4edd0
 
c4edd0
 static gboolean
c4edd0
 gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
c4edd0
 {
c4edd0
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
c4edd0
         GdmDisplayStore *store;
c4edd0
 
c4edd0
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
c4edd0
 
c4edd0
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
c4edd0
 
c4edd0
         g_signal_connect_object (G_OBJECT (store),
c4edd0
                                  "display-added",
c4edd0
                                  G_CALLBACK (on_display_added),
c4edd0
                                  factory,
c4edd0
                                  0);
c4edd0
 
c4edd0
         g_signal_connect_object (G_OBJECT (store),
c4edd0
                                  "display-removed",
c4edd0
                                  G_CALLBACK (on_display_removed),
c4edd0
                                  factory,
c4edd0
                                  0);
c4edd0
 
c4edd0
         gdm_local_display_factory_start_monitor (factory);
c4edd0
-        return gdm_local_display_factory_sync_seats (factory);
c4edd0
+
c4edd0
+        gdm_local_display_factory_sync_seats (factory);
c4edd0
+
c4edd0
+        factory->priv->started = TRUE;
c4edd0
+        return TRUE;
c4edd0
 }
c4edd0
 
c4edd0
 static gboolean
c4edd0
 gdm_local_display_factory_stop (GdmDisplayFactory *base_factory)
c4edd0
 {
c4edd0
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
c4edd0
         GdmDisplayStore *store;
c4edd0
 
c4edd0
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
c4edd0
 
c4edd0
         gdm_local_display_factory_stop_monitor (factory);
c4edd0
 
c4edd0
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
c4edd0
 
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (store),
c4edd0
                                               G_CALLBACK (on_display_added),
c4edd0
                                               factory);
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (store),
c4edd0
                                               G_CALLBACK (on_display_removed),
c4edd0
                                               factory);
c4edd0
 
c4edd0
+        factory->priv->started = FALSE;
c4edd0
+
c4edd0
         return TRUE;
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_local_display_factory_set_property (GObject       *object,
c4edd0
                                         guint          prop_id,
c4edd0
                                         const GValue  *value,
c4edd0
                                         GParamSpec    *pspec)
c4edd0
 {
c4edd0
         switch (prop_id) {
c4edd0
         default:
c4edd0
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
c4edd0
                 break;
c4edd0
         }
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_local_display_factory_get_property (GObject    *object,
c4edd0
                                         guint       prop_id,
c4edd0
                                         GValue     *value,
c4edd0
                                         GParamSpec *pspec)
c4edd0
 {
c4edd0
         switch (prop_id) {
c4edd0
         default:
c4edd0
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
c4edd0
                 break;
c4edd0
         }
c4edd0
 }
c4edd0
 
c4edd0
 static gboolean
c4edd0
@@ -906,50 +917,50 @@ gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass)
c4edd0
         factory_class->stop = gdm_local_display_factory_stop;
c4edd0
 
c4edd0
         g_type_class_add_private (klass, sizeof (GdmLocalDisplayFactoryPrivate));
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_local_display_factory_init (GdmLocalDisplayFactory *factory)
c4edd0
 {
c4edd0
         factory->priv = GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE (factory);
c4edd0
 
c4edd0
         factory->priv->used_display_numbers = g_hash_table_new (NULL, NULL);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_local_display_factory_finalize (GObject *object)
c4edd0
 {
c4edd0
         GdmLocalDisplayFactory *factory;
c4edd0
 
c4edd0
         g_return_if_fail (object != NULL);
c4edd0
         g_return_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (object));
c4edd0
 
c4edd0
         factory = GDM_LOCAL_DISPLAY_FACTORY (object);
c4edd0
 
c4edd0
         g_return_if_fail (factory->priv != NULL);
c4edd0
 
c4edd0
         g_clear_object (&factory->priv->connection);
c4edd0
         g_clear_object (&factory->priv->skeleton);
c4edd0
 
c4edd0
         g_hash_table_destroy (factory->priv->used_display_numbers);
c4edd0
 
c4edd0
-        gdm_local_display_factory_stop_monitor (factory);
c4edd0
+        gdm_local_display_factory_stop (GDM_DISPLAY_FACTORY (factory));
c4edd0
 
c4edd0
         G_OBJECT_CLASS (gdm_local_display_factory_parent_class)->finalize (object);
c4edd0
 }
c4edd0
 
c4edd0
 GdmLocalDisplayFactory *
c4edd0
 gdm_local_display_factory_new (GdmDisplayStore *store)
c4edd0
 {
c4edd0
         if (local_display_factory_object != NULL) {
c4edd0
                 g_object_ref (local_display_factory_object);
c4edd0
         } else {
c4edd0
                 local_display_factory_object = g_object_new (GDM_TYPE_LOCAL_DISPLAY_FACTORY,
c4edd0
                                                              "display-store", store,
c4edd0
                                                              NULL);
c4edd0
                 g_object_add_weak_pointer (local_display_factory_object,
c4edd0
                                            (gpointer *) &local_display_factory_object);
c4edd0
         }
c4edd0
 
c4edd0
         return GDM_LOCAL_DISPLAY_FACTORY (local_display_factory_object);
c4edd0
 }
c4edd0
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
c4edd0
index 1db291587..779b716be 100644
c4edd0
--- a/daemon/gdm-manager.c
c4edd0
+++ b/daemon/gdm-manager.c
c4edd0
@@ -1621,60 +1621,63 @@ greeter_display_started (GdmManager *manager,
c4edd0
         if (manager->priv->ran_once) {
c4edd0
                 return;
c4edd0
         }
c4edd0
 
c4edd0
         maybe_start_pending_initial_login (manager, display);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 on_display_status_changed (GdmDisplay *display,
c4edd0
                            GParamSpec *arg1,
c4edd0
                            GdmManager *manager)
c4edd0
 {
c4edd0
         int         status;
c4edd0
         int         display_number = -1;
c4edd0
         char       *session_type = NULL;
c4edd0
 #ifdef WITH_PLYMOUTH
c4edd0
         gboolean    display_is_local = FALSE;
c4edd0
         gboolean    quit_plymouth = FALSE;
c4edd0
 
c4edd0
         g_object_get (display,
c4edd0
                       "is-local", &display_is_local,
c4edd0
                       NULL);
c4edd0
         quit_plymouth = display_is_local && manager->priv->plymouth_is_running;
c4edd0
 #endif
c4edd0
 
c4edd0
         g_object_get (display,
c4edd0
                       "x11-display-number", &display_number,
c4edd0
                       "session-type", &session_type,
c4edd0
                       NULL);
c4edd0
 
c4edd0
+        if (!manager->priv->started)
c4edd0
+                return;
c4edd0
+
c4edd0
         status = gdm_display_get_status (display);
c4edd0
 
c4edd0
         switch (status) {
c4edd0
                 case GDM_DISPLAY_PREPARED:
c4edd0
                 case GDM_DISPLAY_MANAGED:
c4edd0
                         if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
c4edd0
                             (display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
c4edd0
                                 char *session_class;
c4edd0
 
c4edd0
                                 g_object_get (display,
c4edd0
                                               "session-class", &session_class,
c4edd0
                                               NULL);
c4edd0
                                 if (g_strcmp0 (session_class, "greeter") == 0)
c4edd0
                                         set_up_session (manager, display);
c4edd0
                                 g_free (session_class);
c4edd0
                         }
c4edd0
 
c4edd0
                         if (status == GDM_DISPLAY_MANAGED) {
c4edd0
                                 greeter_display_started (manager, display);
c4edd0
                         }
c4edd0
                         break;
c4edd0
                 case GDM_DISPLAY_FAILED:
c4edd0
                 case GDM_DISPLAY_UNMANAGED:
c4edd0
                 case GDM_DISPLAY_FINISHED:
c4edd0
 #ifdef WITH_PLYMOUTH
c4edd0
                         if (quit_plymouth) {
c4edd0
                                 plymouth_quit_without_transition ();
c4edd0
                                 manager->priv->plymouth_is_running = FALSE;
c4edd0
                         }
c4edd0
 #endif
c4edd0
@@ -2737,60 +2740,62 @@ unexport_display (const char *id,
c4edd0
                   GdmDisplay *display,
c4edd0
                   GdmManager *manager)
c4edd0
 {
c4edd0
         if (!g_dbus_connection_is_closed (manager->priv->connection))
c4edd0
                 g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 finish_display (const char *id,
c4edd0
                 GdmDisplay *display,
c4edd0
                 GdmManager *manager)
c4edd0
 {
c4edd0
         gdm_display_stop_greeter_session (display);
c4edd0
         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
c4edd0
                 gdm_display_unmanage (display);
c4edd0
         gdm_display_finish (display);
c4edd0
 }
c4edd0
 
c4edd0
 static void
c4edd0
 gdm_manager_dispose (GObject *object)
c4edd0
 {
c4edd0
         GdmManager *manager;
c4edd0
 
c4edd0
         g_return_if_fail (object != NULL);
c4edd0
         g_return_if_fail (GDM_IS_MANAGER (object));
c4edd0
 
c4edd0
         manager = GDM_MANAGER (object);
c4edd0
 
c4edd0
         g_return_if_fail (manager->priv != NULL);
c4edd0
 
c4edd0
+        gdm_manager_stop (manager);
c4edd0
+
c4edd0
 #ifdef HAVE_LIBXDMCP
c4edd0
         g_clear_object (&manager->priv->xdmcp_factory);
c4edd0
 #endif
c4edd0
         g_clear_object (&manager->priv->local_factory);
c4edd0
         g_clear_pointer (&manager->priv->open_reauthentication_requests,
c4edd0
                          (GDestroyNotify)
c4edd0
                          g_hash_table_unref);
c4edd0
         g_clear_pointer (&manager->priv->transient_sessions,
c4edd0
                          (GDestroyNotify)
c4edd0
                          g_hash_table_unref);
c4edd0
 
c4edd0
         g_list_foreach (manager->priv->user_sessions,
c4edd0
                         (GFunc) gdm_session_close,
c4edd0
                         NULL);
c4edd0
         g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
c4edd0
         manager->priv->user_sessions = NULL;
c4edd0
 
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c4edd0
                                               G_CALLBACK (on_display_added),
c4edd0
                                               manager);
c4edd0
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
c4edd0
                                               G_CALLBACK (on_display_removed),
c4edd0
                                               manager);
c4edd0
 
c4edd0
         if (!g_dbus_connection_is_closed (manager->priv->connection)) {
c4edd0
                 gdm_display_store_foreach (manager->priv->display_store,
c4edd0
                                            (GdmDisplayStoreFunc)unexport_display,
c4edd0
                                            manager);
c4edd0
                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
c4edd0
         }
c4edd0
-- 
c4edd0
2.21.0
c4edd0