Blob Blame Raw
From d932032d6ad11df0cab868b808d31531c2a1a3c6 Mon Sep 17 00:00:00 2001
From: Michael Catanzaro <mcatanzaro@igalia.com>
Date: Tue, 2 Jul 2019 22:49:30 -0500
Subject: [PATCH] Fix crash in GcalSourceDialog on_source_added

This signal handler can run after the GcalSourceDialog has been
destroyed. We need to use g_signal_connect_object() to fix it.

Also, since this property is writable post-construction, we should
prepare for this to happen and disconnect in set_property() as well.

Probably fixes #418
---
 src/gcal-source-dialog.c | 43 +++++++++++++++++++++++-----------------
 1 file changed, 25 insertions(+), 18 deletions(-)

diff --git a/src/gcal-source-dialog.c b/src/gcal-source-dialog.c
index b1aa1d99..5a65582e 100644
--- a/src/gcal-source-dialog.c
+++ b/src/gcal-source-dialog.c
@@ -2111,29 +2111,36 @@ gcal_source_dialog_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_MANAGER:
-      self->manager = g_value_dup_object (value);
-
-      if (!gcal_manager_get_loading (self->manager))
+      if (self->manager != g_value_get_object (value))
         {
-          GList *sources, *l;
+          if (self->manager != NULL)
+            g_signal_handlers_disconnect_by_data (self->manager, self);
 
-          sources = gcal_manager_get_sources_connected (self->manager);
+          g_set_object (&self->manager, g_value_get_object (value));
 
-          for (l = sources; l != NULL; l = l->next)
-            add_source (self->manager, l->data, is_source_enabled (l->data), self);
-        }
-      else
-        {
-          g_signal_connect_swapped (self->manager,
-                                    "notify::loading",
-                                    G_CALLBACK (loading_changed_cb),
-                                    self);
-        }
+          if (!gcal_manager_get_loading (self->manager))
+            {
+              GList *sources, *l;
 
-      g_signal_connect (self->manager, "source-added", G_CALLBACK (add_source), self);
-      g_signal_connect (self->manager, "source-removed", G_CALLBACK (remove_source), self);
+              sources = gcal_manager_get_sources_connected (self->manager);
 
-      g_object_notify_by_pspec (object, properties[PROP_MANAGER]);
+              for (l = sources; l != NULL; l = l->next)
+                add_source (self->manager, l->data, is_source_enabled (l->data), self);
+            }
+          else
+            {
+              g_signal_connect_object (self->manager,
+                                       "notify::loading",
+                                       G_CALLBACK (loading_changed_cb),
+                                       self,
+                                       G_CONNECT_SWAPPED);
+            }
+
+          g_signal_connect_object (self->manager, "source-added", G_CALLBACK (add_source), self, 0);
+          g_signal_connect_object (self->manager, "source-removed", G_CALLBACK (remove_source), self, 0);
+
+          g_object_notify_by_pspec (object, properties[PROP_MANAGER]);
+        }
       break;
 
     default:
-- 
2.21.0