g_object_unref racy condition can lead to crash

Store whether the object has a toggleref before decrementing the
refcount to prevent race condition when two threads simultaneously
try to unref an object with a refcount of 2.
Patch by Antoine Tremblay.

https://bugzilla.gnome.org/show_bug.cgi?id=551706
This commit is contained in:
Cody Russell 2009-10-06 12:27:12 -04:00
parent afa0db59df
commit 855deaa578

View File

@ -2425,11 +2425,14 @@ g_object_unref (gpointer _object)
old_ref = g_atomic_int_get (&object->ref_count);
if (old_ref > 1)
{
/* valid if last 2 refs are owned by this call to unref and the toggle_ref */
gboolean has_toggle_ref = OBJECT_HAS_TOGGLE_REF (object);
if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1))
goto retry_atomic_decrement1;
/* if we went from 2->1 we need to notify toggle refs if any */
if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
if (old_ref == 2 && has_toggle_ref) /* The last ref being held in this case is owned by the toggle_ref */
toggle_refs_notify (object, TRUE);
}
else
@ -2442,13 +2445,16 @@ g_object_unref (gpointer _object)
old_ref = g_atomic_int_get ((int *)&object->ref_count);
if (old_ref > 1)
{
/* valid if last 2 refs are owned by this call to unref and the toggle_ref */
gboolean has_toggle_ref = OBJECT_HAS_TOGGLE_REF (object);
if (!g_atomic_int_compare_and_exchange ((int *)&object->ref_count, old_ref, old_ref - 1))
goto retry_atomic_decrement2;
/* if we went from 2->1 we need to notify toggle refs if any */
if (old_ref == 2 && OBJECT_HAS_TOGGLE_REF (object))
if (old_ref == 2 && has_toggle_ref) /* The last ref being held in this case is owned by the toggle_ref */
toggle_refs_notify (object, TRUE);
return;
}