mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-07-31 06:13:29 +02:00
gobject: fix racy assertion for toggle-refs
We can only assert for having one toggle reference, after we confirmed
(under lock) that the ref count was in the toggle case.
Otherwise, if another thread refs/unrefs the object, we can hit a wrong
g_critical() assertion about
if (tstackptr->n_toggle_refs != 1)
{
g_critical ("Unexpected number of toggle-refs. g_object_add_toggle_ref() must be paired with g_object_remove_toggle_ref()");
Fixes: 9ae43169cf
('gobject: fix race in toggle ref during g_object_ref()')
This commit is contained in:
committed by
Philip Withnall
parent
58e9e41757
commit
1bb5661198
@@ -4152,9 +4152,10 @@ retry:
|
|||||||
|
|
||||||
/* With ref count 1, check whether we need to emit a toggle notification. */
|
/* With ref count 1, check whether we need to emit a toggle notification. */
|
||||||
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
|
||||||
do_retry = !g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
do_retry = !g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
||||||
old_ref, old_ref + 1, &old_ref);
|
old_ref, old_ref + 1, &old_ref);
|
||||||
|
if (!do_retry)
|
||||||
|
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
||||||
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
if (do_retry)
|
if (do_retry)
|
||||||
goto retry;
|
goto retry;
|
||||||
@@ -4332,8 +4333,6 @@ retry_beginning:
|
|||||||
|
|
||||||
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
|
|
||||||
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
|
||||||
|
|
||||||
if (!g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
if (!g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
||||||
old_ref, old_ref - 1, &old_ref))
|
old_ref, old_ref - 1, &old_ref))
|
||||||
{
|
{
|
||||||
@@ -4341,6 +4340,7 @@ retry_beginning:
|
|||||||
goto retry_beginning;
|
goto retry_beginning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
||||||
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
|
|
||||||
/* Beware: object might be a dangling pointer. */
|
/* Beware: object might be a dangling pointer. */
|
||||||
@@ -4426,10 +4426,11 @@ retry_decrement:
|
|||||||
*
|
*
|
||||||
* In that case, we need a lock to get the toggle notification. */
|
* In that case, we need a lock to get the toggle notification. */
|
||||||
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_lock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
|
||||||
do_retry = !g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
do_retry = !g_atomic_int_compare_and_exchange_full ((int *) &object->ref_count,
|
||||||
old_ref, old_ref - 1,
|
old_ref, old_ref - 1,
|
||||||
&old_ref);
|
&old_ref);
|
||||||
|
if (!do_retry)
|
||||||
|
toggle_notify = toggle_refs_get_notify_unlocked (object, &toggle_data);
|
||||||
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
object_bit_unlock (object, OPTIONAL_BIT_LOCK_TOGGLE_REFS);
|
||||||
|
|
||||||
if (do_retry)
|
if (do_retry)
|
||||||
|
Reference in New Issue
Block a user