From 94ba14d5424c9304342a601cb9eb0842e56d8f51 Mon Sep 17 00:00:00 2001 From: Peter Bloomfield Date: Sun, 3 Jul 2022 14:56:44 -0400 Subject: gobject: Weaken an assertion in g_weak_ref_set() When weak references are being cleaned up, it is possible for the `qdata` for both `quark_weak_locations` and `quark_weak_refs` to have been deallocated, so that `g_datalist_id_get_data()` returns `NULL` for both. This happens when `g_object_run_dispose()` is called for the target of a `GBinding`, and is not an error. See https://gitlab.gnome.org/GNOME/glib/-/issues/2676 --- gobject/gobject.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'gobject') diff --git a/gobject/gobject.c b/gobject/gobject.c index df908984b..2217e5c4b 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -5059,16 +5059,22 @@ g_weak_ref_set (GWeakRef *weak_ref, /* Remove the weak ref from the old object */ if (old_object != NULL) { + gboolean in_weak_refs_notify; + weak_locations = g_datalist_id_get_data (&old_object->qdata, quark_weak_locations); + in_weak_refs_notify = g_datalist_id_get_data (&old_object->qdata, quark_weak_refs) == NULL; /* for it to point to an object, the object must have had it added once */ - g_assert (weak_locations != NULL); - - *weak_locations = g_slist_remove (*weak_locations, weak_ref); + g_assert (weak_locations != NULL || in_weak_refs_notify); - if (!*weak_locations) + if (weak_locations != NULL) { - weak_locations_free_unlocked (weak_locations); - g_datalist_id_remove_no_notify (&old_object->qdata, quark_weak_locations); + *weak_locations = g_slist_remove (*weak_locations, weak_ref); + + if (!*weak_locations) + { + weak_locations_free_unlocked (weak_locations); + g_datalist_id_remove_no_notify (&old_object->qdata, quark_weak_locations); + } } } -- cgit v1.2.1 From 4ef2025d47770ea2da1c4cc9360f21a002d4ed62 Mon Sep 17 00:00:00 2001 From: Peter Bloomfield Date: Sun, 3 Jul 2022 15:10:31 -0400 Subject: gobject/tests/binding: Add a test with run-dispose Add tests in which `g_object_run_dispose()` is called on the source or target of a `GBinding`. After commit a4fa456e677246629e714d05b5de178691571b06, the target test caused a failed assertion in `g_weak_ref_set()` that was not found by the existing tests. Commit 94ba14d5424c9304342a601cb9eb0842e56d8f51 weakens the assertion to allow the test to succeed. See https://gitlab.gnome.org/GNOME/glib/-/issues/2676 --- gobject/tests/binding.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'gobject') diff --git a/gobject/tests/binding.c b/gobject/tests/binding.c index b8373e345..cc6e65987 100644 --- a/gobject/tests/binding.c +++ b/gobject/tests/binding.c @@ -1089,6 +1089,52 @@ binding_concurrent_finalizing (void) } } +static void +binding_dispose_source (void) +{ + /* Test that the source can be disposed */ + BindingSource *source = g_object_new (binding_source_get_type (), NULL); + BindingTarget *target = g_object_new (binding_target_get_type (), NULL); + GBinding *binding; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2676"); + + binding = g_object_bind_property (source, "foo", + target, "bar", + G_BINDING_DEFAULT); + + g_object_add_weak_pointer (G_OBJECT (binding), (gpointer *) &binding); + + g_object_run_dispose (G_OBJECT (source)); + g_assert_null (binding); + + g_object_unref (target); + g_object_unref (source); +} + +static void +binding_dispose_target (void) +{ + /* Test that the target can be disposed */ + BindingSource *source = g_object_new (binding_source_get_type (), NULL); + BindingTarget *target = g_object_new (binding_target_get_type (), NULL); + GBinding *binding; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/-/issues/2676"); + + binding = g_object_bind_property (source, "foo", + target, "bar", + G_BINDING_DEFAULT); + + g_object_add_weak_pointer (G_OBJECT (binding), (gpointer *) &binding); + + g_object_run_dispose (G_OBJECT (target)); + g_assert_null (binding); + + g_object_unref (target); + g_object_unref (source); +} + int main (int argc, char *argv[]) { @@ -1111,6 +1157,8 @@ main (int argc, char *argv[]) g_test_add_func ("/binding/interface", binding_interface); g_test_add_func ("/binding/concurrent-unbind", binding_concurrent_unbind); g_test_add_func ("/binding/concurrent-finalizing", binding_concurrent_finalizing); + g_test_add_func ("/binding/dispose-source", binding_dispose_source); + g_test_add_func ("/binding/dispose-target", binding_dispose_target); return g_test_run (); } -- cgit v1.2.1