From 49030c8797d5a415e2cb94a3c658f67206cb8bf5 Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Wed, 22 May 2013 17:41:32 +0100 Subject: [PATCH] gdbus-peer: Drop some usage of g_thread_yield() It's a recipe for race conditions and error; on some hardware architectures one thread isn't guaranteed to see the results of writes from another thread without a cache flush. https://bugzilla.gnome.org/show_bug.cgi?id=700855 --- gio/tests/gdbus-peer.c | 66 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 23 deletions(-) diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index f85a055..e614e05 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -66,6 +66,8 @@ static const gchar *datapath; static gchar *tmp_address = NULL; static gchar *test_guid = NULL; +static GMutex service_loop_lock; +static GCond service_loop_cond; static GMainLoop *service_loop = NULL; static GDBusServer *server = NULL; static GMainLoop *loop = NULL; @@ -344,6 +346,33 @@ on_new_connection (GDBusServer *server, return TRUE; } +static void +create_service_loop (GMainContext *service_context) +{ + g_assert (service_loop == NULL); + g_mutex_lock (&service_loop_lock); + service_loop = g_main_loop_new (service_context, FALSE); + g_cond_broadcast (&service_loop_cond); + g_mutex_unlock (&service_loop_lock); +} + +static void +teardown_service_loop (void) +{ + g_mutex_lock (&service_loop_lock); + g_clear_pointer (&service_loop, g_main_loop_unref); + g_mutex_unlock (&service_loop_lock); +} + +static void +await_service_loop (void) +{ + g_mutex_lock (&service_loop_lock); + while (service_loop == NULL) + g_cond_wait (&service_loop_cond, &service_loop_lock); + g_mutex_unlock (&service_loop_lock); +} + static gpointer service_thread_func (gpointer user_data) { @@ -399,12 +428,12 @@ service_thread_func (gpointer user_data) g_dbus_server_start (server); - service_loop = g_main_loop_new (service_context, FALSE); + create_service_loop (service_context); g_main_loop_run (service_loop); g_main_context_pop_thread_default (service_context); - g_main_loop_unref (service_loop); + teardown_service_loop (); g_main_context_unref (service_context); /* test code specifically unrefs the server - see below */ @@ -494,12 +523,12 @@ service_thread_func (gpointer data) data); g_socket_service_start (service); - service_loop = g_main_loop_new (service_context, FALSE); + create_service_loop (service_context); g_main_loop_run (service_loop); g_main_context_pop_thread_default (service_context); - g_main_loop_unref (service_loop); + teardown_service_loop (); g_main_context_unref (service_context); g_object_unref (address); @@ -649,12 +678,10 @@ test_peer (void) g_assert (c == NULL); /* bring up a server - we run the server in a different thread to avoid deadlocks */ - service_loop = NULL; service_thread = g_thread_new ("test_peer", service_thread_func, &data); - while (service_loop == NULL) - g_thread_yield (); + await_service_loop (); g_assert (server != NULL); /* bring up a connection and accept it */ @@ -1213,12 +1240,12 @@ nonce_tcp_service_thread_func (gpointer user_data) g_dbus_server_start (server); - service_loop = g_main_loop_new (service_context, FALSE); + create_service_loop (service_context); g_main_loop_run (service_loop); g_main_context_pop_thread_default (service_context); - g_main_loop_unref (service_loop); + teardown_service_loop (); g_main_context_unref (service_context); /* test code specifically unrefs the server - see below */ @@ -1244,15 +1271,12 @@ test_nonce_tcp (void) error = NULL; server = NULL; - service_loop = NULL; service_thread = g_thread_new ("nonce-tcp-service", nonce_tcp_service_thread_func, &data); - while (service_loop == NULL) - g_thread_yield (); + await_service_loop (); g_assert (server != NULL); - /* bring up a connection and accept it */ data.accept_connection = TRUE; error = NULL; @@ -1532,12 +1556,12 @@ tcp_anonymous_service_thread_func (gpointer user_data) g_dbus_server_start (server); - service_loop = g_main_loop_new (service_context, FALSE); + create_service_loop (service_context); g_main_loop_run (service_loop); g_main_context_pop_thread_default (service_context); - g_main_loop_unref (service_loop); + teardown_service_loop (); g_main_context_unref (service_context); return NULL; @@ -1552,12 +1576,10 @@ test_tcp_anonymous (void) GError *error; seen_connection = FALSE; - service_loop = NULL; service_thread = g_thread_new ("tcp-anon-service", tcp_anonymous_service_thread_func, &seen_connection); - while (service_loop == NULL) - g_thread_yield (); + await_service_loop (); g_assert (server != NULL); error = NULL; @@ -1690,14 +1712,14 @@ codegen_service_thread_func (gpointer user_data) G_CALLBACK (codegen_on_new_connection), animal); - service_loop = g_main_loop_new (service_context, FALSE); + create_service_loop (service_context); g_main_loop_run (service_loop); g_object_unref (animal); g_main_context_pop_thread_default (service_context); - g_main_loop_unref (service_loop); + teardown_service_loop (); g_main_context_unref (service_context); g_dbus_server_stop (codegen_server); @@ -1725,12 +1747,10 @@ codegen_test_peer (void) GVariant *value; /* bring up a server - we run the server in a different thread to avoid deadlocks */ - service_loop = NULL; service_thread = g_thread_new ("codegen_test_peer", codegen_service_thread_func, NULL); - while (service_loop == NULL) - g_thread_yield (); + await_service_loop (); g_assert (codegen_server != NULL); /* Get an animal 1 ... */ -- 2.7.4