From 855deaa5780bfef3f6e8b3a41d00d6c7e40ca406 Mon Sep 17 00:00:00 2001 From: Cody Russell Date: Tue, 6 Oct 2009 12:27:12 -0400 Subject: [PATCH] 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 --- gobject/gobject.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/gobject/gobject.c b/gobject/gobject.c index 84324880e..f906d3109 100644 --- a/gobject/gobject.c +++ b/gobject/gobject.c @@ -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; }