mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36: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));
|
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
|
typedef struct
|
||||||
{
|
{
|
||||||
gboolean should_be_last;
|
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-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-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/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", 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-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);
|
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