Blame SOURCES/0001-display-factory-avoid-removing-a-display-from-store-.patch

e0b6b0
From a9422c7b5f4200ad36300bb06134d545bb9d48d2 Mon Sep 17 00:00:00 2001
c90517
From: Lubomir Rintel <lkundrak@v3.sk>
c90517
Date: Tue, 17 Jul 2018 20:20:55 +0000
e0b6b0
Subject: [PATCH 01/51] display-factory: avoid removing a display from store
c90517
 while iterating it
c90517
c90517
---
c90517
 daemon/gdm-display-factory.c       | 41 ++++++++++++++++++++++++++++++
c90517
 daemon/gdm-display-factory.h       |  1 +
c90517
 daemon/gdm-local-display-factory.c |  7 ++---
c90517
 daemon/gdm-xdmcp-display-factory.c |  7 ++---
c90517
 4 files changed, 46 insertions(+), 10 deletions(-)
c90517
c90517
diff --git a/daemon/gdm-display-factory.c b/daemon/gdm-display-factory.c
c90517
index d86a4c8ad..c520e1088 100644
c90517
--- a/daemon/gdm-display-factory.c
c90517
+++ b/daemon/gdm-display-factory.c
c90517
@@ -8,84 +8,120 @@
c90517
  * (at your option) any later version.
c90517
  *
c90517
  * This program is distributed in the hope that it will be useful,
c90517
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
c90517
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
c90517
  * GNU General Public License for more details.
c90517
  *
c90517
  * You should have received a copy of the GNU General Public License
c90517
  * along with this program; if not, write to the Free Software
c90517
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
c90517
  *
c90517
  */
c90517
 
c90517
 #include "config.h"
c90517
 
c90517
 #include <stdlib.h>
c90517
 #include <stdio.h>
c90517
 
c90517
 #include <glib.h>
c90517
 #include <glib/gi18n.h>
c90517
 #include <glib-object.h>
c90517
 
c90517
 #include "gdm-display-factory.h"
c90517
 #include "gdm-display-store.h"
c90517
 
c90517
 #define GDM_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY_FACTORY, GdmDisplayFactoryPrivate))
c90517
 
c90517
 struct GdmDisplayFactoryPrivate
c90517
 {
c90517
         GdmDisplayStore *display_store;
c90517
+        guint            purge_displays_id;
c90517
 };
c90517
 
c90517
 enum {
c90517
         PROP_0,
c90517
         PROP_DISPLAY_STORE,
c90517
 };
c90517
 
c90517
 static void     gdm_display_factory_class_init  (GdmDisplayFactoryClass *klass);
c90517
 static void     gdm_display_factory_init        (GdmDisplayFactory      *factory);
c90517
 static void     gdm_display_factory_finalize    (GObject                *object);
c90517
 
c90517
 G_DEFINE_ABSTRACT_TYPE (GdmDisplayFactory, gdm_display_factory, G_TYPE_OBJECT)
c90517
 
c90517
 GQuark
c90517
 gdm_display_factory_error_quark (void)
c90517
 {
c90517
         static GQuark ret = 0;
c90517
         if (ret == 0) {
c90517
                 ret = g_quark_from_static_string ("gdm_display_factory_error");
c90517
         }
c90517
 
c90517
         return ret;
c90517
 }
c90517
 
c90517
+static gboolean
c90517
+purge_display (char       *id,
c90517
+               GdmDisplay *display,
c90517
+               gpointer    user_data)
c90517
+{
c90517
+        int status;
c90517
+
c90517
+        status = gdm_display_get_status (display);
c90517
+
c90517
+        switch (status) {
c90517
+        case GDM_DISPLAY_FINISHED:
c90517
+        case GDM_DISPLAY_FAILED:
c90517
+                return TRUE;
c90517
+        default:
c90517
+                return FALSE;
c90517
+        }
c90517
+}
c90517
+
c90517
+static void
c90517
+purge_displays (GdmDisplayFactory *factory)
c90517
+{
c90517
+        factory->priv->purge_displays_id = 0;
c90517
+        gdm_display_store_foreach_remove (factory->priv->display_store,
c90517
+                                          (GdmDisplayStoreFunc)purge_display,
c90517
+                                          NULL);
c90517
+}
c90517
+
c90517
+void
c90517
+gdm_display_factory_queue_purge_displays (GdmDisplayFactory *factory)
c90517
+{
c90517
+        if (factory->priv->purge_displays_id == 0) {
c90517
+                factory->priv->purge_displays_id = g_idle_add ((GSourceFunc) purge_displays, factory);
c90517
+        }
c90517
+}
c90517
+
c90517
 GdmDisplayStore *
c90517
 gdm_display_factory_get_display_store (GdmDisplayFactory *factory)
c90517
 {
c90517
         g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), NULL);
c90517
 
c90517
         return factory->priv->display_store;
c90517
 }
c90517
 
c90517
 gboolean
c90517
 gdm_display_factory_start (GdmDisplayFactory *factory)
c90517
 {
c90517
         gboolean ret;
c90517
 
c90517
         g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
c90517
 
c90517
         g_object_ref (factory);
c90517
         ret = GDM_DISPLAY_FACTORY_GET_CLASS (factory)->start (factory);
c90517
         g_object_unref (factory);
c90517
 
c90517
         return ret;
c90517
 }
c90517
 
c90517
 gboolean
c90517
 gdm_display_factory_stop (GdmDisplayFactory *factory)
c90517
 {
c90517
         gboolean ret;
c90517
 
c90517
         g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
c90517
 
c90517
         g_object_ref (factory);
c90517
@@ -160,32 +196,37 @@ gdm_display_factory_class_init (GdmDisplayFactoryClass *klass)
c90517
 
c90517
         g_object_class_install_property (object_class,
c90517
                                          PROP_DISPLAY_STORE,
c90517
                                          g_param_spec_object ("display-store",
c90517
                                                               "display store",
c90517
                                                               "display store",
c90517
                                                               GDM_TYPE_DISPLAY_STORE,
c90517
                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
c90517
 
c90517
         g_type_class_add_private (klass, sizeof (GdmDisplayFactoryPrivate));
c90517
 }
c90517
 
c90517
 static void
c90517
 gdm_display_factory_init (GdmDisplayFactory *factory)
c90517
 {
c90517
         factory->priv = GDM_DISPLAY_FACTORY_GET_PRIVATE (factory);
c90517
 }
c90517
 
c90517
 static void
c90517
 gdm_display_factory_finalize (GObject *object)
c90517
 {
c90517
         GdmDisplayFactory *factory;
c90517
 
c90517
         g_return_if_fail (object != NULL);
c90517
         g_return_if_fail (GDM_IS_DISPLAY_FACTORY (object));
c90517
 
c90517
         factory = GDM_DISPLAY_FACTORY (object);
c90517
 
c90517
         g_return_if_fail (factory->priv != NULL);
c90517
 
c90517
+        if (factory->priv->purge_displays_id != 0) {
c90517
+                g_source_remove (factory->priv->purge_displays_id);
c90517
+                factory->priv->purge_displays_id = 0;
c90517
+        }
c90517
+
c90517
         G_OBJECT_CLASS (gdm_display_factory_parent_class)->finalize (object);
c90517
 }
c90517
diff --git a/daemon/gdm-display-factory.h b/daemon/gdm-display-factory.h
c90517
index 6b30f83dc..1cffa1bd5 100644
c90517
--- a/daemon/gdm-display-factory.h
c90517
+++ b/daemon/gdm-display-factory.h
c90517
@@ -37,34 +37,35 @@ G_BEGIN_DECLS
c90517
 
c90517
 typedef struct GdmDisplayFactoryPrivate GdmDisplayFactoryPrivate;
c90517
 
c90517
 typedef struct
c90517
 {
c90517
         GObject                   parent;
c90517
         GdmDisplayFactoryPrivate *priv;
c90517
 } GdmDisplayFactory;
c90517
 
c90517
 typedef struct
c90517
 {
c90517
         GObjectClass   parent_class;
c90517
 
c90517
         gboolean (*start)                  (GdmDisplayFactory *factory);
c90517
         gboolean (*stop)                   (GdmDisplayFactory *factory);
c90517
 } GdmDisplayFactoryClass;
c90517
 
c90517
 typedef enum
c90517
 {
c90517
          GDM_DISPLAY_FACTORY_ERROR_GENERAL
c90517
 } GdmDisplayFactoryError;
c90517
 
c90517
 #define GDM_DISPLAY_FACTORY_ERROR gdm_display_factory_error_quark ()
c90517
 
c90517
 GQuark                     gdm_display_factory_error_quark             (void);
c90517
 GType                      gdm_display_factory_get_type                (void);
c90517
 
c90517
 gboolean                   gdm_display_factory_start                   (GdmDisplayFactory *manager);
c90517
 gboolean                   gdm_display_factory_stop                    (GdmDisplayFactory *manager);
c90517
 GdmDisplayStore *          gdm_display_factory_get_display_store       (GdmDisplayFactory *manager);
c90517
+void                       gdm_display_factory_queue_purge_displays    (GdmDisplayFactory *manager);
c90517
 
c90517
 G_END_DECLS
c90517
 
c90517
 #endif /* __GDM_DISPLAY_FACTORY_H */
c90517
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
c90517
index ab7e12e91..1a9196ee1 100644
c90517
--- a/daemon/gdm-local-display-factory.c
c90517
+++ b/daemon/gdm-local-display-factory.c
c90517
@@ -222,107 +222,104 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
c90517
                       "seat-id", "seat0",
c90517
                       "allow-timed-login", FALSE,
c90517
                       NULL);
c90517
 
c90517
         store_display (factory, display);
c90517
 
c90517
         if (! gdm_display_manage (display)) {
c90517
                 display = NULL;
c90517
                 goto out;
c90517
         }
c90517
 
c90517
         if (! gdm_display_get_id (display, id, NULL)) {
c90517
                 display = NULL;
c90517
                 goto out;
c90517
         }
c90517
 
c90517
         ret = TRUE;
c90517
  out:
c90517
         /* ref either held by store or not at all */
c90517
         g_object_unref (display);
c90517
 
c90517
         return ret;
c90517
 }
c90517
 
c90517
 static void
c90517
 on_display_status_changed (GdmDisplay             *display,
c90517
                            GParamSpec             *arg1,
c90517
                            GdmLocalDisplayFactory *factory)
c90517
 {
c90517
         int              status;
c90517
-        GdmDisplayStore *store;
c90517
         int              num;
c90517
         char            *seat_id = NULL;
c90517
         char            *session_type = NULL;
c90517
         gboolean         is_initial = TRUE;
c90517
         gboolean         is_local = TRUE;
c90517
 
c90517
         num = -1;
c90517
         gdm_display_get_x11_display_number (display, &num, NULL);
c90517
 
c90517
-        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
c90517
-
c90517
         g_object_get (display,
c90517
                       "seat-id", &seat_id,
c90517
                       "is-initial", &is_initial,
c90517
                       "is-local", &is_local,
c90517
                       "session-type", &session_type,
c90517
                       NULL);
c90517
 
c90517
         status = gdm_display_get_status (display);
c90517
 
c90517
         g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
c90517
         switch (status) {
c90517
         case GDM_DISPLAY_FINISHED:
c90517
                 /* remove the display number from factory->priv->used_display_numbers
c90517
                    so that it may be reused */
c90517
                 if (num != -1) {
c90517
                         g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
c90517
                 }
c90517
-                gdm_display_store_remove (store, display);
c90517
+                gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
c90517
 
c90517
                 /* if this is a local display, do a full resync.  Only
c90517
                  * seats without displays will get created anyway.  This
c90517
                  * ensures we get a new login screen when the user logs out,
c90517
                  * if there isn't one.
c90517
                  */
c90517
                 if (is_local) {
c90517
                         /* reset num failures */
c90517
                         factory->priv->num_failures = 0;
c90517
 
c90517
                         gdm_local_display_factory_sync_seats (factory);
c90517
                 }
c90517
                 break;
c90517
         case GDM_DISPLAY_FAILED:
c90517
                 /* leave the display number in factory->priv->used_display_numbers
c90517
                    so that it doesn't get reused */
c90517
-                gdm_display_store_remove (store, display);
c90517
+                gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
c90517
 
c90517
                 /* Create a new equivalent display if it was static */
c90517
                 if (is_local) {
c90517
 
c90517
                         factory->priv->num_failures++;
c90517
 
c90517
                         if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
c90517
                                 /* oh shit */
c90517
                                 g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
c90517
                         } else {
c90517
 #ifdef ENABLE_WAYLAND_SUPPORT
c90517
                                 if (g_strcmp0 (session_type, "wayland") == 0) {
c90517
                                         g_free (session_type);
c90517
                                         session_type = NULL;
c90517
 
c90517
                                         /* workaround logind race for now
c90517
                                          * bug 1643874
c90517
                                          */
e0b6b0
                                         g_usleep (2 * G_USEC_PER_SEC);
c90517
                                 }
c90517
 
c90517
 #endif
c90517
                                 create_display (factory, seat_id, session_type, is_initial);
c90517
                         }
c90517
                 }
c90517
                 break;
c90517
         case GDM_DISPLAY_UNMANAGED:
c90517
                 break;
c90517
         case GDM_DISPLAY_PREPARED:
c90517
                 break;
c90517
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
c90517
index 46a0d9ffa..5b5786c6f 100644
c90517
--- a/daemon/gdm-xdmcp-display-factory.c
c90517
+++ b/daemon/gdm-xdmcp-display-factory.c
c90517
@@ -2039,93 +2039,90 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
c90517
                 char *ip;
c90517
                 ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
c90517
 
c90517
                 ip = NULL;
c90517
                 gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
c90517
                 g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
c90517
                         ip ? ip : "(null)");
c90517
                 g_free (ip);
c90517
         }
c90517
 
c90517
         freeaddrinfo (ai_list);
c90517
 }
c90517
 
c90517
 static void
c90517
 on_client_disconnected (GdmDisplay *display)
c90517
 {
c90517
         if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
c90517
                 return;
c90517
 
c90517
         gdm_display_stop_greeter_session (display);
c90517
         gdm_display_unmanage (display);
c90517
         gdm_display_finish (display);
c90517
 }
c90517
 
c90517
 static void
c90517
 on_display_status_changed (GdmDisplay             *display,
c90517
                            GParamSpec             *arg1,
c90517
                            GdmXdmcpDisplayFactory *factory)
c90517
 {
c90517
         int              status;
c90517
-        GdmDisplayStore *store;
c90517
         GdmLaunchEnvironment *launch_environment;
c90517
         GdmSession *session;
c90517
         GdmAddress *address;
c90517
         gint32  session_number;
c90517
         int display_number;
c90517
 
c90517
-        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
c90517
-
c90517
         launch_environment = NULL;
c90517
         g_object_get (display, "launch-environment", &launch_environment, NULL);
c90517
 
c90517
         session = NULL;
c90517
         if (launch_environment != NULL) {
c90517
                 session = gdm_launch_environment_get_session (launch_environment);
c90517
         }
c90517
 
c90517
         status = gdm_display_get_status (display);
c90517
 
c90517
         g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
c90517
         switch (status) {
c90517
         case GDM_DISPLAY_FINISHED:
c90517
                 g_object_get (display,
c90517
                               "remote-address", &address,
c90517
                               "x11-display-number", &display_number,
c90517
                               "session-number", &session_number,
c90517
                               NULL);
c90517
                 gdm_xdmcp_send_alive (factory, address, display_number, session_number);
c90517
 
c90517
-                gdm_display_store_remove (store, display);
c90517
+                gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
c90517
                 break;
c90517
         case GDM_DISPLAY_FAILED:
c90517
-                gdm_display_store_remove (store, display);
c90517
+                gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
c90517
                 break;
c90517
         case GDM_DISPLAY_UNMANAGED:
c90517
                 if (session != NULL) {
c90517
                         g_signal_handlers_disconnect_by_func (G_OBJECT (session),
c90517
                                                               G_CALLBACK (on_client_disconnected),
c90517
                                                               display);
c90517
                 }
c90517
                 break;
c90517
         case GDM_DISPLAY_PREPARED:
c90517
                 break;
c90517
         case GDM_DISPLAY_MANAGED:
c90517
                 if (session != NULL) {
c90517
                         g_signal_connect_object (G_OBJECT (session),
c90517
                                                  "client-disconnected",
c90517
                                                  G_CALLBACK (on_client_disconnected),
c90517
                                                  display, G_CONNECT_SWAPPED);
c90517
                         g_signal_connect_object (G_OBJECT (session),
c90517
                                                  "disconnected",
c90517
                                                  G_CALLBACK (on_client_disconnected),
c90517
                                                  display, G_CONNECT_SWAPPED);
c90517
                 }
c90517
                 break;
c90517
         default:
c90517
                 g_assert_not_reached ();
c90517
                 break;
c90517
         }
c90517
 }
c90517
 
c90517
 static GdmDisplay *
c90517
 gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
c90517
-- 
e0b6b0
2.27.0
c90517