Revert "Merge branch 'th/gobj-doc-weakref' into 'main'"

This change appears to cause crashes. Revert for now, to investigate why
exactly that happens.

This reverts commit 22f57fce781efb2a5f348f4878c11770eea7e900, reversing
changes made to 549a966b46042081228fa4a276bb428e53b11f7c.

Fixes: https://gitlab.gnome.org/GNOME/glib/-/issues/3684
See-also: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4584#note_2436512
See-also: https://gitlab.gnome.org/GNOME/gnome-builder/-/issues/2324
This commit is contained in:
Thomas Haller 2025-05-09 20:34:18 +02:00
parent 3674b4a805
commit 3cf6d22f76
3 changed files with 37 additions and 57 deletions

View File

@ -387,10 +387,31 @@ weak_unbind (gpointer user_data,
source = g_weak_ref_get (&context->source);
target = g_weak_ref_get (&context->target);
/* FIXME: note that another thread might (at this point) race to call
* g_object_run_dispose(). In that case, unbind_internal_locked() will
* also try to unref the weak notifications and we get a double
* binding_context_unref(). */
/* If this is called then either the source or target or both must be in the
* process of being disposed. If this happens as part of g_object_unref()
* then the weak references are actually cleared, otherwise if disposing
* happens as part of g_object_run_dispose() then they would still point to
* the disposed object.
*
* If the object this is being called for is either the source or the target
* and we actually got a strong reference to it nonetheless (see above),
* then signal handlers and weak notifies for it are already disconnected
* and they must not be disconnected a second time. Instead simply clear the
* weak reference and be done with it.
*
* See https://gitlab.gnome.org/GNOME/glib/-/issues/2266 */
if (source == where_the_object_was)
{
g_weak_ref_set (&context->source, NULL);
g_clear_object (&source);
}
if (target == where_the_object_was)
{
g_weak_ref_set (&context->target, NULL);
g_clear_object (&target);
}
binding_was_removed = unbind_internal_locked (context, binding, source, target);

View File

@ -1912,13 +1912,6 @@ g_object_dispatch_properties_changed (GObject *object,
* reference cycles.
*
* This function should only be called from object system implementations.
*
* This function temporarily acquires another strong reference while running
* dispose.
*
* This first clears all #GWeakRef pointers and then calls
* #GObjectClass.dispose. (Before 2.86, #GWeakRef pointers were
* cleared after #GObjectClass.dispose).
*/
void
g_object_run_dispose (GObject *object)
@ -1930,6 +1923,10 @@ g_object_run_dispose (GObject *object)
g_object_ref (object);
TRACE (GOBJECT_OBJECT_DISPOSE(object,G_TYPE_FROM_INSTANCE(object), 0));
G_OBJECT_GET_CLASS (object)->dispose (object);
TRACE (GOBJECT_OBJECT_DISPOSE_END(object,G_TYPE_FROM_INSTANCE(object), 0));
if ((object_get_optional_flags (object) & OPTIONAL_FLAG_EVER_HAD_WEAK_REF))
{
wrdata = weak_ref_data_get_surely (object);
@ -1938,10 +1935,6 @@ g_object_run_dispose (GObject *object)
weak_ref_data_unlock (wrdata);
}
TRACE (GOBJECT_OBJECT_DISPOSE (object, G_TYPE_FROM_INSTANCE (object), 0));
G_OBJECT_GET_CLASS (object)->dispose (object);
TRACE (GOBJECT_OBJECT_DISPOSE_END (object, G_TYPE_FROM_INSTANCE (object), 0));
g_object_unref (object);
}
@ -5842,19 +5835,15 @@ g_initially_unowned_class_init (GInitiallyUnownedClass *klass)
* atomic with respect to invalidation of weak pointers to destroyed
* objects.
*
* #GWeakRefs are reset before calling #GObjectClass.dispose.
* If the object's #GObjectClass.dispose method results in additional
* references to the object being held (re-referencing), any #GWeakRefs taken
* before it was disposed will continue to point to %NULL. If during disposal
* the object gets re-referenced and resurrected, the #GWeakRefs taken during
* disposal will be set until the reference count drops towards zero again and
* #GObjectClass.dispose is called again. If #GWeakRefs were taken during
* disposal but the object not resurrected, they will be set to %NULL right
* after, before finalization.
* before it was disposed will continue to point to %NULL. Any #GWeakRefs taken
* during disposal and after re-referencing, or after disposal has returned due
* to the re-referencing, will continue to point to the object until its refcount
* goes back to zero, at which point they too will be invalidated.
*
* Note that #GObjectClass.run_dispose() also resets #GWeakRefs. As such, the
* #GWeakRef actually tracks whether #GObjectClass.dispose() was called
* and not the reference count reaching zero.
* It is invalid to take a #GWeakRef on an object during #GObjectClass.dispose
* without first having or creating a strong reference to the object.
*/
#define WEAK_REF_LOCK_BIT 0

View File

@ -654,29 +654,9 @@ test_weak_ref_on_dispose (void)
g_assert_null (g_weak_ref_get (&weak));
}
static GWeakRef *_weak_ref_on_run_dispose_weak = NULL;
static void
_weak_ref_on_run_dispose_weak_cb (gpointer data,
GObject *where_the_object_was)
test_weak_ref_on_run_dispose (void)
{
g_assert_nonnull (_weak_ref_on_run_dispose_weak);
g_assert_true (_weak_ref_on_run_dispose_weak == data);
/* It is important that GWeakRef are cleared *before* we emit notifications.
* For example, see weak_unbind() which relies on this.
*
* See also: https://gitlab.gnome.org/GNOME/glib/-/merge_requests/4586 */
g_assert_null (g_weak_ref_get (data));
_weak_ref_on_run_dispose_weak = NULL;
}
static void
test_weak_ref_on_run_dispose (gconstpointer test_data)
{
const gboolean WITH_WEAK_NOTIFY = GPOINTER_TO_INT (test_data);
GObject *obj;
GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
@ -689,16 +669,7 @@ test_weak_ref_on_run_dispose (gconstpointer test_data)
g_assert_true (obj == g_weak_ref_get (&weak));
g_object_unref (obj);
if (WITH_WEAK_NOTIFY)
{
/* Inside the weak notification, we expect the weakref to be NULL
* already. */
_weak_ref_on_run_dispose_weak = &weak;
g_object_weak_ref (obj, _weak_ref_on_run_dispose_weak_cb, &weak);
}
g_object_run_dispose (obj);
g_assert_null (_weak_ref_on_run_dispose_weak);
g_assert_null (g_weak_ref_get (&weak));
g_weak_ref_set (&weak, obj);
@ -1675,8 +1646,7 @@ main (int argc, char **argv)
g_test_add_func ("/object/weak-pointer/set-function", test_weak_pointer_set_function);
g_test_add_func ("/object/weak-ref", test_weak_ref);
g_test_add_func ("/object/weak-ref/on-dispose", test_weak_ref_on_dispose);
g_test_add_data_func ("/object/weak-ref/on-run-dispose/with-weak-notify", GINT_TO_POINTER (TRUE), test_weak_ref_on_run_dispose);
g_test_add_data_func ("/object/weak-ref/on-run-dispose/without-weak-notify", GINT_TO_POINTER (FALSE), test_weak_ref_on_run_dispose);
g_test_add_func ("/object/weak-ref/on-run-dispose", test_weak_ref_on_run_dispose);
g_test_add_func ("/object/weak-ref/on-toggle-notify", test_weak_ref_on_toggle_notify);
g_test_add_func ("/object/weak-ref/in-toggle-notify", test_weak_ref_in_toggle_notify);
g_test_add_func ("/object/weak-ref/many", test_weak_ref_many);