summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2010-11-12 09:03:38 -0500
committerMatthias Clasen <mclasen@redhat.com>2010-11-12 09:03:53 -0500
commit56e0ff2fb8cf551f330b1d6a7361c5d70d5856bb (patch)
treeaaa60d58b7f32466804573906710ec3d5dbd3437
parent633b2bc6113e06c4977cfa2c27bcbb5623bf07a9 (diff)
Protect access to closure, weak refs and toggle refs arrays
This fixes https://bugzilla.gnome.org/show_bug.cgi?id=613822 (cherry picked from commit b7616114c6c1884c3a183a4d83156bdf2151b731)
-rw-r--r--gobject/gobject.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 22095c28c..328b905c7 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -184,6 +184,9 @@ static void object_interface_check_properties (gpointer func_da
/* --- variables --- */
+G_LOCK_DEFINE_STATIC (closure_array_mutex);
+G_LOCK_DEFINE_STATIC (weak_refs_mutex);
+G_LOCK_DEFINE_STATIC (toggle_refs_mutex);
static GQuark quark_closure_array = 0;
static GQuark quark_weak_refs = 0;
static GQuark quark_toggle_refs = 0;
@@ -2231,6 +2234,7 @@ g_object_weak_ref (GObject *object,
g_return_if_fail (notify != NULL);
g_return_if_fail (object->ref_count >= 1);
+ G_LOCK (weak_refs_mutex);
wstack = g_datalist_id_remove_no_notify (&object->qdata, quark_weak_refs);
if (wstack)
{
@@ -2247,6 +2251,7 @@ g_object_weak_ref (GObject *object,
wstack->weak_refs[i].notify = notify;
wstack->weak_refs[i].data = data;
g_datalist_id_set_data_full (&object->qdata, quark_weak_refs, wstack, weak_refs_notify);
+ G_UNLOCK (weak_refs_mutex);
}
/**
@@ -2268,6 +2273,7 @@ g_object_weak_unref (GObject *object,
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (notify != NULL);
+ G_LOCK (weak_refs_mutex);
wstack = g_datalist_id_get_data (&object->qdata, quark_weak_refs);
if (wstack)
{
@@ -2285,6 +2291,7 @@ g_object_weak_unref (GObject *object,
break;
}
}
+ G_UNLOCK (weak_refs_mutex);
if (!found_one)
g_warning ("%s: couldn't find weak ref %p(%p)", G_STRFUNC, notify, data);
}
@@ -2442,13 +2449,18 @@ static void
toggle_refs_notify (GObject *object,
gboolean is_last_ref)
{
- ToggleRefStack *tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
+ ToggleRefStack tstack, *tstackptr;
+
+ G_LOCK (toggle_refs_mutex);
+ tstackptr = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
+ tstack = *tstackptr;
+ G_UNLOCK (toggle_refs_mutex);
/* Reentrancy here is not as tricky as it seems, because a toggle reference
* will only be notified when there is exactly one of them.
*/
- g_assert (tstack->n_toggle_refs == 1);
- tstack->toggle_refs[0].notify (tstack->toggle_refs[0].data, tstack->object, is_last_ref);
+ g_assert (tstack.n_toggle_refs == 1);
+ tstack.toggle_refs[0].notify (tstack.toggle_refs[0].data, tstack.object, is_last_ref);
}
/**
@@ -2504,6 +2516,7 @@ g_object_add_toggle_ref (GObject *object,
g_object_ref (object);
+ G_LOCK (toggle_refs_mutex);
tstack = g_datalist_id_remove_no_notify (&object->qdata, quark_toggle_refs);
if (tstack)
{
@@ -2528,6 +2541,7 @@ g_object_add_toggle_ref (GObject *object,
tstack->toggle_refs[i].data = data;
g_datalist_id_set_data_full (&object->qdata, quark_toggle_refs, tstack,
(GDestroyNotify)g_free);
+ G_UNLOCK (toggle_refs_mutex);
}
/**
@@ -2554,6 +2568,7 @@ g_object_remove_toggle_ref (GObject *object,
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (notify != NULL);
+ G_LOCK (toggle_refs_mutex);
tstack = g_datalist_id_get_data (&object->qdata, quark_toggle_refs);
if (tstack)
{
@@ -2571,13 +2586,14 @@ g_object_remove_toggle_ref (GObject *object,
if (tstack->n_toggle_refs == 0)
g_datalist_unset_flags (&object->qdata, OBJECT_HAS_TOGGLE_REF_FLAG);
- g_object_unref (object);
-
break;
}
}
-
- if (!found_one)
+ G_UNLOCK (toggle_refs_mutex);
+
+ if (found_one)
+ g_object_unref (object);
+ else
g_warning ("%s: couldn't find toggle ref %p(%p)", G_STRFUNC, notify, data);
}
@@ -3238,17 +3254,21 @@ object_remove_closure (gpointer data,
GClosure *closure)
{
GObject *object = data;
- CArray *carray = g_object_get_qdata (object, quark_closure_array);
+ CArray *carray;
guint i;
+ G_LOCK (closure_array_mutex);
+ carray = g_object_get_qdata (object, quark_closure_array);
for (i = 0; i < carray->n_closures; i++)
if (carray->closures[i] == closure)
{
carray->n_closures--;
if (i < carray->n_closures)
carray->closures[i] = carray->closures[carray->n_closures];
+ G_UNLOCK (closure_array_mutex);
return;
}
+ G_UNLOCK (closure_array_mutex);
g_assert_not_reached ();
}
@@ -3304,6 +3324,7 @@ g_object_watch_closure (GObject *object,
g_closure_add_marshal_guards (closure,
object, (GClosureNotify) g_object_ref,
object, (GClosureNotify) g_object_unref);
+ G_LOCK (closure_array_mutex);
carray = g_datalist_id_remove_no_notify (&object->qdata, quark_closure_array);
if (!carray)
{
@@ -3319,6 +3340,7 @@ g_object_watch_closure (GObject *object,
}
carray->closures[i] = closure;
g_datalist_id_set_data_full (&object->qdata, quark_closure_array, carray, destroy_closure_array);
+ G_UNLOCK (closure_array_mutex);
}
/**