diff options
author | Lubomir Rintel <lkundrak@v3.sk> | 2018-07-17 20:20:55 +0000 |
---|---|---|
committer | Ray Strode <rstrode@redhat.com> | 2021-04-12 16:57:53 -0400 |
commit | e7bfb9dd88235e8251a225ef4317f9c2196a4e75 (patch) | |
tree | 938e2a9c302e03253402dc9515d22cac7618bc05 | |
parent | be723c344bba3640ff8d4e431aa25b7efe40660c (diff) | |
download | gdm-e7bfb9dd88235e8251a225ef4317f9c2196a4e75.tar.gz |
display-factory: avoid removing a display from store while iterating it
-rw-r--r-- | daemon/gdm-display-factory.c | 41 | ||||
-rw-r--r-- | daemon/gdm-display-factory.h | 1 | ||||
-rw-r--r-- | daemon/gdm-local-display-factory.c | 7 | ||||
-rw-r--r-- | daemon/gdm-xdmcp-display-factory.c | 7 |
4 files changed, 46 insertions, 10 deletions
diff --git a/daemon/gdm-display-factory.c b/daemon/gdm-display-factory.c index d86a4c8a..c520e108 100644 --- a/daemon/gdm-display-factory.c +++ b/daemon/gdm-display-factory.c @@ -35,6 +35,7 @@ struct GdmDisplayFactoryPrivate { GdmDisplayStore *display_store; + guint purge_displays_id; }; enum { @@ -59,6 +60,41 @@ gdm_display_factory_error_quark (void) return ret; } +static gboolean +purge_display (char *id, + GdmDisplay *display, + gpointer user_data) +{ + int status; + + status = gdm_display_get_status (display); + + switch (status) { + case GDM_DISPLAY_FINISHED: + case GDM_DISPLAY_FAILED: + return TRUE; + default: + return FALSE; + } +} + +static void +purge_displays (GdmDisplayFactory *factory) +{ + factory->priv->purge_displays_id = 0; + gdm_display_store_foreach_remove (factory->priv->display_store, + (GdmDisplayStoreFunc)purge_display, + NULL); +} + +void +gdm_display_factory_queue_purge_displays (GdmDisplayFactory *factory) +{ + if (factory->priv->purge_displays_id == 0) { + factory->priv->purge_displays_id = g_idle_add ((GSourceFunc) purge_displays, factory); + } +} + GdmDisplayStore * gdm_display_factory_get_display_store (GdmDisplayFactory *factory) { @@ -187,5 +223,10 @@ gdm_display_factory_finalize (GObject *object) g_return_if_fail (factory->priv != NULL); + if (factory->priv->purge_displays_id != 0) { + g_source_remove (factory->priv->purge_displays_id); + factory->priv->purge_displays_id = 0; + } + G_OBJECT_CLASS (gdm_display_factory_parent_class)->finalize (object); } diff --git a/daemon/gdm-display-factory.h b/daemon/gdm-display-factory.h index 6b30f83d..1cffa1bd 100644 --- a/daemon/gdm-display-factory.h +++ b/daemon/gdm-display-factory.h @@ -64,6 +64,7 @@ GType gdm_display_factory_get_type (void); gboolean gdm_display_factory_start (GdmDisplayFactory *manager); gboolean gdm_display_factory_stop (GdmDisplayFactory *manager); GdmDisplayStore * gdm_display_factory_get_display_store (GdmDisplayFactory *manager); +void gdm_display_factory_queue_purge_displays (GdmDisplayFactory *manager); G_END_DECLS diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 6856d30d..1c7daeb1 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -251,7 +251,6 @@ on_display_status_changed (GdmDisplay *display, GdmLocalDisplayFactory *factory) { int status; - GdmDisplayStore *store; int num; char *seat_id = NULL; char *session_id = NULL; @@ -264,8 +263,6 @@ on_display_status_changed (GdmDisplay *display, num = -1; gdm_display_get_x11_display_number (display, &num, NULL); - store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); - g_object_get (display, "seat-id", &seat_id, "session-id", &session_id, @@ -285,7 +282,7 @@ on_display_status_changed (GdmDisplay *display, if (num != -1) { g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num)); } - gdm_display_store_remove (store, display); + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); /* if this is a local display, recreate the display so * a new login screen comes up if one is missing. @@ -318,7 +315,7 @@ on_display_status_changed (GdmDisplay *display, case GDM_DISPLAY_FAILED: /* leave the display number in factory->priv->used_display_numbers so that it doesn't get reused */ - gdm_display_store_remove (store, display); + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); /* Create a new equivalent display if it was static */ if (is_local) { diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c index 46a0d9ff..5b5786c6 100644 --- a/daemon/gdm-xdmcp-display-factory.c +++ b/daemon/gdm-xdmcp-display-factory.c @@ -2066,15 +2066,12 @@ on_display_status_changed (GdmDisplay *display, GdmXdmcpDisplayFactory *factory) { int status; - GdmDisplayStore *store; GdmLaunchEnvironment *launch_environment; GdmSession *session; GdmAddress *address; gint32 session_number; int display_number; - store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); - launch_environment = NULL; g_object_get (display, "launch-environment", &launch_environment, NULL); @@ -2095,10 +2092,10 @@ on_display_status_changed (GdmDisplay *display, NULL); gdm_xdmcp_send_alive (factory, address, display_number, session_number); - gdm_display_store_remove (store, display); + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); break; case GDM_DISPLAY_FAILED: - gdm_display_store_remove (store, display); + gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory)); break; case GDM_DISPLAY_UNMANAGED: if (session != NULL) { |