diff --git a/gobject/gbinding.c b/gobject/gbinding.c index 562f339da..48b4fbaec 100644 --- a/gobject/gbinding.c +++ b/gobject/gbinding.c @@ -388,11 +388,30 @@ weak_unbind (gpointer user_data, target = g_weak_ref_get (&context->target); /* If this is called then either the source or target or both must be in the - * process of being finalized and their weak reference must be reset to NULL - * already. + * 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 source==target then both will always be NULL here. */ - g_assert (source == NULL || target == NULL); + * 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); @@ -627,10 +646,6 @@ g_binding_unbind_internal (GBinding *binding, source = g_weak_ref_get (&context->source); target = g_weak_ref_get (&context->target); - /* If the binding was removed previously, source and target are both NULL. - * Otherwise both will not be NULL. */ - g_assert ((source == NULL && target == NULL) || (source != NULL && target != NULL)); - binding_was_removed = unbind_internal_locked (context, binding, source, target); g_mutex_unlock (&binding->unbind_lock); diff --git a/gobject/gobject.c b/gobject/gobject.c index 863d5b67a..2617dca3e 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -2975,7 +2975,7 @@ weak_refs_notify (gpointer data) * @data: extra data to pass to notify * * Adds a weak reference callback to an object. Weak references are - * used for notification when an object is finalized. They are called + * used for notification when an object is disposed. They are called * "weak references" because they allow you to safely hold a pointer * to an object without calling g_object_ref() (g_object_ref() adds a * strong reference, that is, forces the object to stay alive). diff --git a/gobject/gobject.h b/gobject/gobject.h index a84c183f8..aec8975e4 100644 --- a/gobject/gobject.h +++ b/gobject/gobject.h @@ -227,11 +227,11 @@ typedef void (*GObjectFinalizeFunc) (GObject *object); /** * GWeakNotify: * @data: data that was provided when the weak reference was established - * @where_the_object_was: the object being finalized + * @where_the_object_was: the object being disposed * * A #GWeakNotify function can be added to an object as a callback that gets * triggered when the object is finalized. Since the object is already being - * finalized when the #GWeakNotify is called, there's not much you could do + * disposed when the #GWeakNotify is called, there's not much you could do * with the object, apart from e.g. using its address as hash-index or the like. */ typedef void (*GWeakNotify) (gpointer data,