summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2018-07-17 20:20:55 +0000
committerRay Strode <halfline@gmail.com>2018-07-17 20:20:55 +0000
commitfeb1cf50ccc9d5e8066aa47d69c53bb39f9dff82 (patch)
tree78e722c9f1f13ad674cd6045b41c3711d226888a
parent79a7360ba632d71c7d3b0fd9143419dcc46fb924 (diff)
downloadgdm-feb1cf50ccc9d5e8066aa47d69c53bb39f9dff82.tar.gz
display-factory: avoid removing a display from store while iterating it
-rw-r--r--daemon/gdm-display-factory.c41
-rw-r--r--daemon/gdm-display-factory.h1
-rw-r--r--daemon/gdm-local-display-factory.c7
-rw-r--r--daemon/gdm-xdmcp-display-factory.c7
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 b29f5ac5..25d30f5b 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -249,7 +249,6 @@ on_display_status_changed (GdmDisplay *display,
GdmLocalDisplayFactory *factory)
{
int status;
- GdmDisplayStore *store;
int num;
char *seat_id = NULL;
char *session_type = NULL;
@@ -259,8 +258,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,
"is-initial", &is_initial,
@@ -278,7 +275,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, do a full resync. Only
* seats without displays will get created anyway. This
@@ -295,7 +292,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) {