Blame SOURCES/0001-local-display-factory-Don-t-try-to-respawn-displays-.patch

6b1540
From d8fd8d4d6ff6a119f6bd27eb07316384c4776d12 Mon Sep 17 00:00:00 2001
6b1540
From: Ray Strode <rstrode@redhat.com>
6b1540
Date: Wed, 15 Sep 2021 11:23:17 -0400
6b1540
Subject: [PATCH] local-display-factory: Don't try to respawn displays on
6b1540
 shutdown
6b1540
6b1540
At the moment in the shutdown path we may try to respawn displays
6b1540
that just got killed.
6b1540
6b1540
The respawning happens when things are half torn down leading to
6b1540
crashes.
6b1540
6b1540
This commit makes sure we turn off the respawn logic in the shutdown
6b1540
path.
6b1540
---
6b1540
 daemon/gdm-local-display-factory.c | 11 ++++++++++-
6b1540
 daemon/gdm-manager.c               |  2 ++
6b1540
 2 files changed, 12 insertions(+), 1 deletion(-)
6b1540
6b1540
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
6b1540
index 11dcda2c..a0884893 100644
6b1540
--- a/daemon/gdm-local-display-factory.c
6b1540
+++ b/daemon/gdm-local-display-factory.c
6b1540
@@ -46,60 +46,62 @@
6b1540
 #define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
6b1540
 #define GDM_MANAGER_DBUS_NAME               "org.gnome.DisplayManager.LocalDisplayFactory"
6b1540
 
6b1540
 #define MAX_DISPLAY_FAILURES 5
6b1540
 #define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
6b1540
 #define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */
6b1540
 
6b1540
 struct _GdmLocalDisplayFactory
6b1540
 {
6b1540
         GdmDisplayFactory              parent;
6b1540
 
6b1540
         GdmDBusLocalDisplayFactory *skeleton;
6b1540
         GDBusConnection *connection;
6b1540
         GHashTable      *used_display_numbers;
6b1540
 
6b1540
         /* FIXME: this needs to be per seat? */
6b1540
         guint            num_failures;
6b1540
 
6b1540
         guint            seat_new_id;
6b1540
         guint            seat_removed_id;
6b1540
         guint            seat_properties_changed_id;
6b1540
 
6b1540
         gboolean         seat0_graphics_check_timed_out;
6b1540
         guint            seat0_graphics_check_timeout_id;
6b1540
 
6b1540
 #if defined(ENABLE_USER_DISPLAY_SERVER)
6b1540
         unsigned int     active_vt;
6b1540
         guint            active_vt_watch_id;
6b1540
         guint            wait_to_finish_timeout_id;
6b1540
 #endif
6b1540
+
6b1540
+        gboolean         is_started;
6b1540
 };
6b1540
 
6b1540
 enum {
6b1540
         PROP_0,
6b1540
 };
6b1540
 
6b1540
 static void     gdm_local_display_factory_class_init    (GdmLocalDisplayFactoryClass *klass);
6b1540
 static void     gdm_local_display_factory_init          (GdmLocalDisplayFactory      *factory);
6b1540
 static void     gdm_local_display_factory_finalize      (GObject                     *object);
6b1540
 
6b1540
 static void     ensure_display_for_seat                 (GdmLocalDisplayFactory      *factory,
6b1540
                                                          const char                  *seat_id);
6b1540
 
6b1540
 static void     on_display_status_changed               (GdmDisplay                  *display,
6b1540
                                                          GParamSpec                  *arg1,
6b1540
                                                          GdmLocalDisplayFactory      *factory);
6b1540
 
6b1540
 static gboolean gdm_local_display_factory_sync_seats    (GdmLocalDisplayFactory *factory);
6b1540
 static gpointer local_display_factory_object = NULL;
6b1540
 static gboolean lookup_by_session_id (const char *id,
6b1540
                                       GdmDisplay *display,
6b1540
                                       gpointer    user_data);
6b1540
 
6b1540
 G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
6b1540
 
6b1540
 GQuark
6b1540
 gdm_local_display_factory_error_quark (void)
6b1540
 {
6b1540
         static GQuark ret = 0;
6b1540
         if (ret == 0) {
6b1540
@@ -478,60 +480,64 @@ on_session_registered_cb (GObject *gobject,
6b1540
                           GParamSpec *pspec,
6b1540
                           gpointer user_data)
6b1540
 {
6b1540
         GdmDisplay *display = GDM_DISPLAY (gobject);
6b1540
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
6b1540
         gboolean registered;
6b1540
 
6b1540
         g_object_get (display, "session-registered", &registered, NULL);
6b1540
 
6b1540
         if (!registered)
6b1540
                 return;
6b1540
 
6b1540
         g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill");
6b1540
 
6b1540
         finish_waiting_displays_on_seat (factory, "seat0");
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 on_display_status_changed (GdmDisplay             *display,
6b1540
                            GParamSpec             *arg1,
6b1540
                            GdmLocalDisplayFactory *factory)
6b1540
 {
6b1540
         int              status;
6b1540
         int              num;
6b1540
         char            *seat_id = NULL;
6b1540
         char            *session_type = NULL;
6b1540
         char            *session_class = NULL;
6b1540
         gboolean         is_initial = TRUE;
6b1540
         gboolean         is_local = TRUE;
6b1540
 
6b1540
+
6b1540
+        if (!factory->is_started)
6b1540
+                return;
6b1540
+
6b1540
         num = -1;
6b1540
         gdm_display_get_x11_display_number (display, &num, NULL);
6b1540
 
6b1540
         g_object_get (display,
6b1540
                       "seat-id", &seat_id,
6b1540
                       "is-initial", &is_initial,
6b1540
                       "is-local", &is_local,
6b1540
                       "session-type", &session_type,
6b1540
                       "session-class", &session_class,
6b1540
                       NULL);
6b1540
 
6b1540
         status = gdm_display_get_status (display);
6b1540
 
6b1540
         g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
6b1540
         switch (status) {
6b1540
         case GDM_DISPLAY_FINISHED:
6b1540
                 /* remove the display number from factory->used_display_numbers
6b1540
                    so that it may be reused */
6b1540
                 if (num != -1) {
6b1540
                         g_hash_table_remove (factory->used_display_numbers, GUINT_TO_POINTER (num));
6b1540
                 }
6b1540
                 gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
6b1540
 
6b1540
                 /* if this is a local display, do a full resync.  Only
6b1540
                  * seats without displays will get created anyway.  This
6b1540
                  * ensures we get a new login screen when the user logs out,
6b1540
                  * if there isn't one.
6b1540
                  */
6b1540
                 if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
6b1540
                         /* reset num failures */
6b1540
@@ -1250,99 +1256,102 @@ on_display_added (GdmDisplayStore        *display_store,
6b1540
 
6b1540
         display = gdm_display_store_lookup (display_store, id);
6b1540
 
6b1540
         if (display != NULL) {
6b1540
                 g_signal_connect_object (display, "notify::status",
6b1540
                                          G_CALLBACK (on_display_status_changed),
6b1540
                                          factory,
6b1540
                                          0);
6b1540
 
6b1540
                 g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
6b1540
         }
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 on_display_removed (GdmDisplayStore        *display_store,
6b1540
                     GdmDisplay             *display,
6b1540
                     GdmLocalDisplayFactory *factory)
6b1540
 {
6b1540
         g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
6b1540
         g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
6b1540
 }
6b1540
 
6b1540
 static gboolean
6b1540
 gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
6b1540
 {
6b1540
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
6b1540
         GdmDisplayStore *store;
6b1540
 
6b1540
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
6b1540
 
6b1540
+        factory->is_started = TRUE;
6b1540
+
6b1540
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
6b1540
 
6b1540
         g_signal_connect_object (G_OBJECT (store),
6b1540
                                  "display-added",
6b1540
                                  G_CALLBACK (on_display_added),
6b1540
                                  factory,
6b1540
                                  0);
6b1540
 
6b1540
         g_signal_connect_object (G_OBJECT (store),
6b1540
                                  "display-removed",
6b1540
                                  G_CALLBACK (on_display_removed),
6b1540
                                  factory,
6b1540
                                  0);
6b1540
 
6b1540
         gdm_local_display_factory_start_monitor (factory);
6b1540
         return gdm_local_display_factory_sync_seats (factory);
6b1540
 }
6b1540
 
6b1540
 static gboolean
6b1540
 gdm_local_display_factory_stop (GdmDisplayFactory *base_factory)
6b1540
 {
6b1540
         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
6b1540
         GdmDisplayStore *store;
6b1540
 
6b1540
         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
6b1540
 
6b1540
         gdm_local_display_factory_stop_monitor (factory);
6b1540
 
6b1540
         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
6b1540
 
6b1540
         g_signal_handlers_disconnect_by_func (G_OBJECT (store),
6b1540
                                               G_CALLBACK (on_display_added),
6b1540
                                               factory);
6b1540
         g_signal_handlers_disconnect_by_func (G_OBJECT (store),
6b1540
                                               G_CALLBACK (on_display_removed),
6b1540
                                               factory);
6b1540
-
6b1540
         g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove);
6b1540
 
6b1540
+        factory->is_started = FALSE;
6b1540
+
6b1540
         return TRUE;
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 gdm_local_display_factory_set_property (GObject       *object,
6b1540
                                         guint          prop_id,
6b1540
                                         const GValue  *value,
6b1540
                                         GParamSpec    *pspec)
6b1540
 {
6b1540
         switch (prop_id) {
6b1540
         default:
6b1540
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
6b1540
                 break;
6b1540
         }
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 gdm_local_display_factory_get_property (GObject    *object,
6b1540
                                         guint       prop_id,
6b1540
                                         GValue     *value,
6b1540
                                         GParamSpec *pspec)
6b1540
 {
6b1540
         switch (prop_id) {
6b1540
         default:
6b1540
                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
6b1540
                 break;
6b1540
         }
6b1540
 }
6b1540
 
6b1540
 static gboolean
6b1540
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
6b1540
index b3d0a2b5..4b62b8b1 100644
6b1540
--- a/daemon/gdm-manager.c
6b1540
+++ b/daemon/gdm-manager.c
6b1540
@@ -2774,60 +2774,62 @@ unexport_display (const char *id,
6b1540
                   GdmDisplay *display,
6b1540
                   GdmManager *manager)
6b1540
 {
6b1540
         if (!g_dbus_connection_is_closed (manager->priv->connection))
6b1540
                 g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 finish_display (const char *id,
6b1540
                 GdmDisplay *display,
6b1540
                 GdmManager *manager)
6b1540
 {
6b1540
         gdm_display_stop_greeter_session (display);
6b1540
         if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
6b1540
                 gdm_display_unmanage (display);
6b1540
         gdm_display_finish (display);
6b1540
 }
6b1540
 
6b1540
 static void
6b1540
 gdm_manager_dispose (GObject *object)
6b1540
 {
6b1540
         GdmManager *manager;
6b1540
 
6b1540
         g_return_if_fail (object != NULL);
6b1540
         g_return_if_fail (GDM_IS_MANAGER (object));
6b1540
 
6b1540
         manager = GDM_MANAGER (object);
6b1540
 
6b1540
         g_return_if_fail (manager->priv != NULL);
6b1540
 
6b1540
+        gdm_manager_stop (manager);
6b1540
+
6b1540
         g_clear_weak_pointer (&manager->priv->automatic_login_display);
6b1540
 
6b1540
 #ifdef HAVE_LIBXDMCP
6b1540
         g_clear_object (&manager->priv->xdmcp_factory);
6b1540
 #endif
6b1540
         g_clear_object (&manager->priv->local_factory);
6b1540
         g_clear_pointer (&manager->priv->open_reauthentication_requests,
6b1540
                          g_hash_table_unref);
6b1540
         g_clear_pointer (&manager->priv->transient_sessions,
6b1540
                          g_hash_table_unref);
6b1540
 
6b1540
         g_list_foreach (manager->priv->user_sessions,
6b1540
                         (GFunc) gdm_session_close,
6b1540
                         NULL);
6b1540
         g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
6b1540
         manager->priv->user_sessions = NULL;
6b1540
 
6b1540
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
6b1540
                                               G_CALLBACK (on_display_added),
6b1540
                                               manager);
6b1540
         g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
6b1540
                                               G_CALLBACK (on_display_removed),
6b1540
                                               manager);
6b1540
 
6b1540
         if (!g_dbus_connection_is_closed (manager->priv->connection)) {
6b1540
                 gdm_display_store_foreach (manager->priv->display_store,
6b1540
                                            (GdmDisplayStoreFunc)unexport_display,
6b1540
                                            manager);
6b1540
                 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
6b1540
         }
6b1540
-- 
6b1540
2.31.1
6b1540