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