diff options
author | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2022-06-22 00:37:22 +0200 |
---|---|---|
committer | Marco Trevisan (Treviño) <mail@3v1n0.net> | 2022-06-23 20:01:12 +0200 |
commit | e218371f1906500437b12f641b86517e5c427cc7 (patch) | |
tree | 44bf693ec316f7518e4ff45e078b525142f9e6e2 | |
parent | 62192925b6ea3597043d7771be58ba7a21a8407b (diff) | |
download | glib-e218371f1906500437b12f641b86517e5c427cc7.tar.gz |
gio/tests: Ensure that cancellable is cancelled when emitting the signal
Use a race between threads resetting and cancelling a cancellable and
ensure that when we call the callback the cancellable is cancelled
-rw-r--r-- | gio/tests/cancellable.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/gio/tests/cancellable.c b/gio/tests/cancellable.c index c51d13f29..d27cd7c74 100644 --- a/gio/tests/cancellable.c +++ b/gio/tests/cancellable.c @@ -578,6 +578,70 @@ test_cancellable_disconnect_on_cancelled_callback_hangs (void) g_object_unref (cancellable); } +static gpointer +repeatedly_cancelling_thread (gpointer data) +{ + GCancellable *cancellable = data; + const guint iterations = 10000; + + for (guint i = 0; i < iterations; ++i) + g_cancellable_cancel (cancellable); + + return NULL; +} + +static gpointer +repeatedly_resetting_thread (gpointer data) +{ + GCancellable *cancellable = data; + const guint iterations = 10000; + + for (guint i = 0; i < iterations; ++i) + g_cancellable_reset (cancellable); + + return NULL; +} + +static void +on_racy_cancellable_cancelled (GCancellable *cancellable, + gpointer data) +{ + gboolean *callback_called = data; + + g_assert_true (g_cancellable_is_cancelled (cancellable)); + g_atomic_int_set (callback_called, TRUE); +} + +static void +test_cancellable_cancel_reset_races (void) +{ + GCancellable *cancellable; + GThread *resetting_thread = NULL; + GThread *cancelling_thread = NULL; + gboolean callback_called = FALSE; + + g_test_summary ("Tests threads racing for cancelling and resetting a GCancellable"); + + cancellable = g_cancellable_new (); + + g_cancellable_connect (cancellable, G_CALLBACK (on_racy_cancellable_cancelled), + &callback_called, NULL); + g_assert_false (callback_called); + + resetting_thread = g_thread_new ("/cancellable/cancel-reset-races/resetting", + repeatedly_resetting_thread, + cancellable); + cancelling_thread = g_thread_new ("/cancellable/cancel-reset-races/cancelling", + repeatedly_cancelling_thread, cancellable); + + g_thread_join (g_steal_pointer (&cancelling_thread)); + g_thread_join (g_steal_pointer (&resetting_thread)); + + g_assert_true (callback_called); + + g_object_unref (cancellable); +} + int main (int argc, char *argv[]) { @@ -589,6 +653,7 @@ main (int argc, char *argv[]) g_test_add_func ("/cancellable/poll-fd", test_cancellable_poll_fd); g_test_add_func ("/cancellable/poll-fd-cancelled", test_cancellable_cancelled_poll_fd); g_test_add_func ("/cancellable/poll-fd-cancelled-threaded", test_cancellable_cancelled_poll_fd_threaded); + g_test_add_func ("/cancellable/cancel-reset-races", test_cancellable_cancel_reset_races); g_test_add_func ("/cancellable-source/threaded-dispose", test_cancellable_source_threaded_dispose); return g_test_run (); |