mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
gobject/tests/reference: add test for deadlock related to GWeakRef and toggle reference
GWeakRef calls g_object_ref() while holding a read lock. g_object_ref() can emit a toggle notification. If you then inside the toggle notification setup a GWeakRef (to the same or another object), the code will try to get a write lock. Deadlock will happen. Add a test to "show" that (the breaking part is commented out). Will be fixed next.
This commit is contained in:
parent
dd2b6d7e3f
commit
787861761d
@ -719,6 +719,56 @@ test_weak_ref_on_toggle_notify (void)
|
||||
g_assert_null (g_weak_ref_get (&weak));
|
||||
}
|
||||
|
||||
static void
|
||||
weak_ref_in_toggle_notify_toggle_cb (gpointer data,
|
||||
GObject *object,
|
||||
gboolean is_last_ref)
|
||||
{
|
||||
GWeakRef weak2;
|
||||
GObject *obj2;
|
||||
|
||||
if (is_last_ref)
|
||||
return;
|
||||
|
||||
/* We just got a second ref, while calling g_weak_ref_get().
|
||||
* At this point, we hold a lock for the weak ref.
|
||||
*
|
||||
* FIXME: currently we would dead lock with the lines below.
|
||||
*/
|
||||
return;
|
||||
|
||||
g_weak_ref_init (&weak2, object);
|
||||
g_assert_true (object == g_weak_ref_get (&weak2));
|
||||
g_object_unref (object);
|
||||
|
||||
obj2 = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
g_weak_ref_set (&weak2, obj2);
|
||||
g_object_unref (obj2);
|
||||
|
||||
g_assert_null (g_weak_ref_get (&weak2));
|
||||
}
|
||||
|
||||
static void
|
||||
test_weak_ref_in_toggle_notify (void)
|
||||
{
|
||||
GObject *obj;
|
||||
GWeakRef weak = { { GUINT_TO_POINTER (0xDEADBEEFU) } };
|
||||
|
||||
obj = g_object_new (G_TYPE_OBJECT, NULL);
|
||||
g_object_add_toggle_ref (obj, weak_ref_in_toggle_notify_toggle_cb, NULL);
|
||||
g_object_unref (obj);
|
||||
|
||||
g_weak_ref_init (&weak, obj);
|
||||
|
||||
/* We trigger a toggle notify via g_weak_ref_get(). */
|
||||
g_assert_true (g_weak_ref_get (&weak) == obj);
|
||||
|
||||
g_object_remove_toggle_ref (obj, weak_ref_in_toggle_notify_toggle_cb, NULL);
|
||||
g_object_unref (obj);
|
||||
|
||||
g_assert_null (g_weak_ref_get (&weak));
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean should_be_last;
|
||||
@ -1365,6 +1415,7 @@ main (int argc, char **argv)
|
||||
g_test_add_func ("/object/weak-ref/on-dispose", test_weak_ref_on_dispose);
|
||||
g_test_add_func ("/object/weak-ref/on-run-dispose", test_weak_ref_on_run_dispose);
|
||||
g_test_add_func ("/object/weak-ref/on-toggle-notify", test_weak_ref_on_toggle_notify);
|
||||
g_test_add_func ("/object/weak-ref/in-toggle-notify", test_weak_ref_in_toggle_notify);
|
||||
g_test_add_func ("/object/toggle-ref", test_toggle_ref);
|
||||
g_test_add_func ("/object/toggle-ref/ref-on-dispose", test_toggle_ref_on_dispose);
|
||||
g_test_add_func ("/object/toggle-ref/ref-and-notify-on-dispose", test_toggle_ref_and_notify_on_dispose);
|
||||
|
Loading…
Reference in New Issue
Block a user