[gnome-builder] signal-group: Only temporarily ref the GTypeClass



commit 35e9cad6973f8b583f37c7d2af8d5ed70b47a189
Author: Garrett Regier <garrett regier riftio com>
Date:   Tue Jun 2 05:12:01 2015 -0700

    signal-group: Only temporarily ref the GTypeClass
    
    Also add a test for this issue.

 contrib/egg/egg-signal-group.c |   27 +++++++++------------------
 tests/test-egg-signal-group.c  |   31 +++++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+), 18 deletions(-)
---
diff --git a/contrib/egg/egg-signal-group.c b/contrib/egg/egg-signal-group.c
index 956c3bd..2e76185 100644
--- a/contrib/egg/egg-signal-group.c
+++ b/contrib/egg/egg-signal-group.c
@@ -54,7 +54,6 @@ struct _EggSignalGroup
 
   GObject    *target;
   GPtrArray  *handlers;
-  GTypeClass *target_type_class;
   GType       target_type;
   gsize       block_count;
 };
@@ -102,22 +101,16 @@ static void
 egg_signal_group_set_target_type (EggSignalGroup *self,
                                   GType           target_type)
 {
-  g_return_if_fail (EGG_IS_SIGNAL_GROUP (self));
+  g_assert (EGG_IS_SIGNAL_GROUP (self));
+  g_assert (g_type_is_a (target_type, G_TYPE_OBJECT));
 
-  if (target_type != 0)
-    {
-      self->target_type = target_type;
-      /*
-       * FIXME:
-       *
-       * We can get into situations where the registration of a type via
-       * g_type_ensure(TYPE_FOO) is not enough to be able to parse signal
-       * names on TYPE_FOO. Therefore, we hold onto a reference to the type
-       * to ensure that the signal information has been loaded.
-       * This is released when the instance is disposed.
-       */
-      self->target_type_class = g_type_class_ref (target_type);
-    }
+  self->target_type = target_type;
+
+  /* The class must be created at least once for the signals
+   * to be registered, otherwise g_signal_parse_name() will fail
+   */
+  if (g_type_class_peek (target_type) == NULL)
+    g_type_class_unref (g_type_class_ref (target_type));
 }
 
 static void
@@ -448,7 +441,6 @@ egg_signal_group_dispose (GObject *object)
 
   egg_signal_group_unbind (self);
   g_clear_pointer (&self->handlers, g_ptr_array_unref);
-  g_clear_pointer (&self->target_type_class, g_type_class_unref);
 
   G_OBJECT_CLASS (egg_signal_group_parent_class)->dispose (object);
 }
@@ -615,7 +607,6 @@ egg_signal_group_connect_full (EggSignalGroup *self,
   GQuark signal_detail;
 
   g_return_if_fail (EGG_IS_SIGNAL_GROUP (self));
-  g_return_if_fail (self->target_type != 0);
   g_return_if_fail (detailed_signal != NULL);
   g_return_if_fail (g_signal_parse_name (detailed_signal, self->target_type,
                                          &signal_id, &signal_detail, FALSE) != 0);
diff --git a/tests/test-egg-signal-group.c b/tests/test-egg-signal-group.c
index 269e339..500f099 100644
--- a/tests/test-egg-signal-group.c
+++ b/tests/test-egg-signal-group.c
@@ -421,6 +421,35 @@ test_signal_group_connect_object (void)
   g_object_unref (target);
 }
 
+static void
+test_signal_group_signal_parsing (void)
+{
+  g_test_trap_subprocess ("/Egg/SignalGroup/signal-parsing/subprocess", 0,
+                          G_TEST_SUBPROCESS_INHERIT_STDERR);
+  g_test_trap_assert_passed ();
+  g_test_trap_assert_stderr ("");
+}
+
+static void
+test_signal_group_signal_parsing_subprocess (void)
+{
+  EggSignalGroup *group;
+
+  /* Check that the class has not been created and with it the
+   * signals registered. This will cause g_signal_parse_name()
+   * to fail unless EggSignalGroup calls g_type_class_ref().
+   */
+  g_assert_null (g_type_class_peek (signal_target_get_type ()));
+
+  group = egg_signal_group_new (signal_target_get_type ());
+  egg_signal_group_connect (group,
+                            "the-signal",
+                            G_CALLBACK (connect_before_cb),
+                            NULL);
+
+  g_object_unref (group);
+}
+
 gint
 main (gint   argc,
       gchar *argv[])
@@ -432,5 +461,7 @@ main (gint   argc,
   g_test_add_func ("/Egg/SignalGroup/blocking", test_signal_group_blocking);
   g_test_add_func ("/Egg/SignalGroup/weak-ref-target", test_signal_group_weak_ref_target);
   g_test_add_func ("/Egg/SignalGroup/connect-object", test_signal_group_connect_object);
+  g_test_add_func ("/Egg/SignalGroup/signal-parsing", test_signal_group_signal_parsing);
+  g_test_add_func ("/Egg/SignalGroup/signal-parsing/subprocess", 
test_signal_group_signal_parsing_subprocess);
   return g_test_run ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]