mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-06-21 19:54:51 +02:00
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:
parent
3674b4a805
commit
3cf6d22f76
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user