You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
325 lines
12 KiB
325 lines
12 KiB
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", ®istered, 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 |
|
|
|
|