From 430c5635f245ca485f09035f1b6c3a59dd69758c Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Thu, 13 Oct 2011 01:00:57 -0400 Subject: [PATCH] g_thread_new: never fail Remove the GError argument from g_thread_new() and abort on failure. Introduce g_thread_try() for those who want to handle failure. --- gio/gdbusprivate.c | 5 +---- gio/tests/contexts.c | 2 +- gio/tests/gdbus-export.c | 7 +------ gio/tests/gdbus-peer.c | 14 ++++--------- gio/tests/gdbus-proxy-threads.c | 4 +--- gio/tests/gdbus-test-codegen.c | 3 +-- gio/tests/gdbus-threading.c | 24 ++++------------------ gio/tests/resolver.c | 4 +--- gio/tests/send-data.c | 4 +--- gio/tests/socket-client.c | 4 +--- gio/tests/socket-server.c | 4 +--- gio/tests/socket.c | 3 +-- gio/tests/tls-interaction.c | 3 +-- gio/tests/unix-streams.c | 4 ++-- glib/glib.symbols | 1 + glib/gmain.c | 6 +----- glib/gthread.c | 40 +++++++++++++++++++++++++++++++++---- glib/gthread.h | 3 +++ glib/gthreadpool.c | 2 +- glib/tests/once.c | 2 +- glib/tests/thread.c | 6 +++--- gobject/tests/dynamictests.c | 2 +- gthread/tests/1bit-mutex.c | 3 +-- gthread/tests/atomic.c | 2 +- gthread/tests/gwakeuptest.c | 2 +- gthread/tests/spawn-multithreaded.c | 6 ++---- 26 files changed, 73 insertions(+), 87 deletions(-) diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index b5c770b..c30a4ec 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -287,7 +287,6 @@ static SharedThreadData * _g_dbus_shared_thread_ref (void) { static gsize shared_thread_data = 0; - GError *error = NULL; SharedThreadData *ret; if (g_once_init_enter (&shared_thread_data)) @@ -304,9 +303,7 @@ _g_dbus_shared_thread_ref (void) data->loop = g_main_loop_new (data->context, FALSE); data->thread = g_thread_new ("gdbus", gdbus_shared_thread_func, - data, - &error); - g_assert_no_error (error); + data); /* We can cast between gsize and gpointer safely */ g_once_init_leave (&shared_thread_data, (gsize) data); } diff --git a/gio/tests/contexts.c b/gio/tests/contexts.c index 17bfe4a..de00464 100644 --- a/gio/tests/contexts.c +++ b/gio/tests/contexts.c @@ -75,7 +75,7 @@ idle_start_test1_thread (gpointer loop) gboolean io_completed; g_mutex_lock (&test1_mutex); - thread = g_thread_new ("test1", test1_thread, NULL, NULL); + thread = g_thread_new ("test1", test1_thread, NULL); g_get_current_time (&time); time.tv_sec += 2; diff --git a/gio/tests/gdbus-export.c b/gio/tests/gdbus-export.c index 9ee1c3d..424d031 100644 --- a/gio/tests/gdbus-export.c +++ b/gio/tests/gdbus-export.c @@ -936,16 +936,11 @@ static void test_dispatch (const gchar *object_path) { GThread *thread; - GError *error; /* run this in a thread to avoid deadlocks */ - error = NULL; thread = g_thread_new ("test_dispatch", test_dispatch_thread_func, - (gpointer) object_path, - &error); - g_assert_no_error (error); - g_assert (thread != NULL); + (gpointer) object_path); g_main_loop_run (loop); g_thread_join (thread); } diff --git a/gio/tests/gdbus-peer.c b/gio/tests/gdbus-peer.c index 93995dd..ee2ceb6 100644 --- a/gio/tests/gdbus-peer.c +++ b/gio/tests/gdbus-peer.c @@ -601,11 +601,9 @@ test_peer (void) g_assert (c == NULL); /* bring up a server - we run the server in a different thread to avoid deadlocks */ - error = NULL; service_thread = g_thread_new ("test_peer", service_thread_func, - &data, - &error); + &data); while (service_loop == NULL) g_thread_yield (); g_assert (server != NULL); @@ -1050,11 +1048,9 @@ delayed_message_processing (void) data = g_new0 (DmpData, 1); - error = NULL; service_thread = g_thread_new ("dmp", dmp_thread_func, - data, - &error); + data); while (data->server == NULL || !g_dbus_server_is_active (data->server)) g_thread_yield (); @@ -1201,8 +1197,7 @@ test_nonce_tcp (void) service_loop = NULL; service_thread = g_thread_new ("nonce-tcp-service", nonce_tcp_service_thread_func, - &data, - &error); + &data); while (service_loop == NULL) g_thread_yield (); g_assert (server != NULL); @@ -1510,8 +1505,7 @@ test_tcp_anonymous (void) service_loop = NULL; service_thread = g_thread_new ("tcp-anon-service", tcp_anonymous_service_thread_func, - &seen_connection, /* user_data */ - &error); + &seen_connection); while (service_loop == NULL) g_thread_yield (); g_assert (server != NULL); diff --git a/gio/tests/gdbus-proxy-threads.c b/gio/tests/gdbus-proxy-threads.c index 0e03209..325c68b 100644 --- a/gio/tests/gdbus-proxy-threads.c +++ b/gio/tests/gdbus-proxy-threads.c @@ -222,9 +222,7 @@ test_proxy (void) for (i = 0; i < n_threads; i++) { proxy_threads[i] = g_thread_new ("run-proxy", - run_proxy_thread, connection, - &error); - g_assert_no_error (error); + run_proxy_thread, connection); } g_main_loop_run (loop); diff --git a/gio/tests/gdbus-test-codegen.c b/gio/tests/gdbus-test-codegen.c index 7652615..3b4ac76 100644 --- a/gio/tests/gdbus-test-codegen.c +++ b/gio/tests/gdbus-test-codegen.c @@ -567,8 +567,7 @@ on_name_acquired (GDBusConnection *connection, g_thread_new ("check-proxies", check_proxies_in_thread, - loop, - NULL); + loop); } static void diff --git a/gio/tests/gdbus-threading.c b/gio/tests/gdbus-threading.c index d77b578..be85513 100644 --- a/gio/tests/gdbus-threading.c +++ b/gio/tests/gdbus-threading.c @@ -229,16 +229,11 @@ test_delivery_in_thread_func (gpointer _data) static void test_delivery_in_thread (void) { - GError *error; GThread *thread; - error = NULL; thread = g_thread_new ("deliver", test_delivery_in_thread_func, - NULL, - &error); - g_assert_no_error (error); - g_assert (thread != NULL); + NULL); /* run the event loop - it is needed to dispatch D-Bus messages */ g_main_loop_run (loop); @@ -379,12 +374,10 @@ test_method_calls_on_proxy (GDBusProxy *proxy) SyncThreadData data1; SyncThreadData data2; SyncThreadData data3; - GError *error; GTimeVal start_time; GTimeVal end_time; guint elapsed_msec; - error = NULL; do_async = (n == 0); g_get_current_time (&start_time); @@ -396,10 +389,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data1.done = FALSE; thread1 = g_thread_new ("sleep", test_sleep_in_thread_func, - &data1, - &error); - g_assert_no_error (error); - g_assert (thread1 != NULL); + &data1); data2.proxy = proxy; data2.msec = 20; @@ -408,10 +398,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data2.done = FALSE; thread2 = g_thread_new ("sleep2", test_sleep_in_thread_func, - &data2, - &error); - g_assert_no_error (error); - g_assert (thread2 != NULL); + &data2); data3.proxy = proxy; data3.msec = 100; @@ -420,10 +407,7 @@ test_method_calls_on_proxy (GDBusProxy *proxy) data3.done = FALSE; thread3 = g_thread_new ("sleep3", test_sleep_in_thread_func, - &data3, - &error); - g_assert_no_error (error); - g_assert (thread3 != NULL); + &data3); /* we handle messages in the main loop - threads will quit it when they are done */ while (!(data1.done && data2.done && data3.done)) diff --git a/gio/tests/resolver.c b/gio/tests/resolver.c index 3af0218..8c474b2 100644 --- a/gio/tests/resolver.c +++ b/gio/tests/resolver.c @@ -203,9 +203,7 @@ start_sync_lookups (char **argv, int argc) for (i = 0; i < argc; i++) { GThread *thread; - - thread = g_thread_new ("lookup", lookup_thread, argv[i], NULL); - g_assert (thread != NULL); + thread = g_thread_new ("lookup", lookup_thread, argv[i]); g_thread_unref (thread); } } diff --git a/gio/tests/send-data.c b/gio/tests/send-data.c index 8d005c8..01a42b4 100644 --- a/gio/tests/send-data.c +++ b/gio/tests/send-data.c @@ -91,10 +91,8 @@ main (int argc, char *argv[]) if (cancel_timeout) { GThread *thread; - cancellable = g_cancellable_new (); - thread = g_thread_new ("cancel", cancel_thread, cancellable, NULL); - g_assert (thread != NULL); + thread = g_thread_new ("cancel", cancel_thread, cancellable); g_thread_unref (thread); } else diff --git a/gio/tests/socket-client.c b/gio/tests/socket-client.c index 0b49fc1..ca06c0f 100644 --- a/gio/tests/socket-client.c +++ b/gio/tests/socket-client.c @@ -289,10 +289,8 @@ main (int argc, if (cancel_timeout) { GThread *thread; - cancellable = g_cancellable_new (); - thread = g_thread_new ("cancel", cancel_thread, cancellable, NULL); - g_assert (thread != NULL); + thread = g_thread_new ("cancel", cancel_thread, cancellable); g_thread_unref (thread); } else diff --git a/gio/tests/socket-server.c b/gio/tests/socket-server.c index 2f1126c..b89edb5 100644 --- a/gio/tests/socket-server.c +++ b/gio/tests/socket-server.c @@ -82,10 +82,8 @@ main (int argc, if (cancel_timeout) { GThread *thread; - cancellable = g_cancellable_new (); - thread = g_thread_new ("cancel", cancel_thread, cancellable, NULL); - g_assert (thread != NULL); + thread = g_thread_new ("cancel", cancel_thread, cancellable); g_thread_unref (thread); } else diff --git a/gio/tests/socket.c b/gio/tests/socket.c index 3f27bcb..4e0710f 100644 --- a/gio/tests/socket.c +++ b/gio/tests/socket.c @@ -128,8 +128,7 @@ create_server (GSocketFamily family, g_socket_listen (server, &error); g_assert_no_error (error); - data->thread = g_thread_new ("server", server_thread, data, &error); - g_assert_no_error (error); + data->thread = g_thread_new ("server", server_thread, data); return data; } diff --git a/gio/tests/tls-interaction.c b/gio/tests/tls-interaction.c index cd7866d..ff0db2b 100644 --- a/gio/tests/tls-interaction.c +++ b/gio/tests/tls-interaction.c @@ -426,7 +426,6 @@ static void setup_with_thread_loop (Test *test, gconstpointer user_data) { - GError *error = NULL; ThreadLoop closure; setup_without_loop (test, user_data); @@ -437,7 +436,7 @@ setup_with_thread_loop (Test *test, closure.test = test; g_mutex_lock (&closure.loop_mutex); - test->loop_thread = g_thread_new ("loop", thread_loop, &closure, &error); + test->loop_thread = g_thread_new ("loop", thread_loop, &closure); while (!closure.started) g_cond_wait (&closure.loop_started, &closure.loop_mutex); g_mutex_unlock (&closure.loop_mutex); diff --git a/gio/tests/unix-streams.c b/gio/tests/unix-streams.c index 6ff5877..aaf8aa8 100644 --- a/gio/tests/unix-streams.c +++ b/gio/tests/unix-streams.c @@ -216,8 +216,8 @@ test_pipe_io (void) reader_cancel = g_cancellable_new (); main_cancel = g_cancellable_new (); - writer = g_thread_new ("writer", writer_thread, NULL, NULL); - reader = g_thread_new ("reader", reader_thread, NULL, NULL); + writer = g_thread_new ("writer", writer_thread, NULL); + reader = g_thread_new ("reader", reader_thread, NULL); in = g_unix_input_stream_new (writer_pipe[0], TRUE); out = g_unix_output_stream_new (reader_pipe[1], TRUE); diff --git a/glib/glib.symbols b/glib/glib.symbols index 29d43a4..b156bcc 100644 --- a/glib/glib.symbols +++ b/glib/glib.symbols @@ -1103,6 +1103,7 @@ g_thread_new_full g_thread_ref g_thread_self g_thread_set_priority +g_thread_try g_thread_use_default_impl g_thread_unref g_thread_yield diff --git a/glib/gmain.c b/glib/gmain.c index 1a3c67a..ef9ac46 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -4757,12 +4757,8 @@ g_get_worker_context (void) if (g_once_init_enter (&initialised)) { - GError *error = NULL; - glib_worker_context = g_main_context_new (); - if (g_thread_new ("gmain", glib_worker_main, NULL, &error) == NULL) - g_error ("Creating GLib worker thread failed: %s\n", error->message); - + g_thread_new ("gmain", glib_worker_main, NULL); g_once_init_leave (&initialised, TRUE); } diff --git a/glib/gthread.c b/glib/gthread.c index 1567b5f..2cdac53 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -731,17 +731,48 @@ g_thread_proxy (gpointer data) * a debugger. Some systems restrict the length of @name to * 16 bytes. * - * @error can be %NULL to ignore errors, or non-%NULL to report errors. - * The error is set, if and only if the function returns %NULL. + * If the thread can not be created the program aborts. See + * g_thread_try() if you want to attempt to deal with failures. * - * You must + * Returns: the new #GThread + * + * Since: 2.32 + */ +GThread * +g_thread_new (const gchar *name, + GThreadFunc func, + gpointer data) +{ + GError *error = NULL; + GThread *thread; + + thread = g_thread_new_internal (name, g_thread_proxy, func, data, 0, &error); + + if G_UNLIKELY (thread == NULL) + g_error ("creating thread '%s': %s", name ? name : "", error->message); + + return thread; +} + +/** + * g_thread_try: + * @name: a name for the new thread + * @func: a function to execute in the new thread + * @data: an argument to supply to the new thread + * @error: return location for error + * + * This function is the same as g_thread_new() except that it allows for + * the possibility of failure. + * + * If a thread can not be created (due to resource limits), @error is + * set and %NULL is returned. * * Returns: the new #GThread, or %NULL if an error occurred * * Since: 2.32 */ GThread * -g_thread_new (const gchar *name, +g_thread_try (const gchar *name, GThreadFunc func, gpointer data, GError **error) @@ -749,6 +780,7 @@ g_thread_new (const gchar *name, return g_thread_new_internal (name, g_thread_proxy, func, data, 0, error); } + /** * g_thread_new_full: * @name: a name for the new thread diff --git a/glib/gthread.h b/glib/gthread.h index 3b08016..6400f69 100644 --- a/glib/gthread.h +++ b/glib/gthread.h @@ -141,6 +141,9 @@ GThread * g_thread_ref (GThread *thread); void g_thread_unref (GThread *thread); GThread * g_thread_new (const gchar *name, GThreadFunc func, + gpointer data); +GThread * g_thread_try (const gchar *name, + GThreadFunc func, gpointer data, GError **error); GThread * g_thread_new_full (const gchar *name, diff --git a/glib/gthreadpool.c b/glib/gthreadpool.c index d2402f8..a07628f 100644 --- a/glib/gthreadpool.c +++ b/glib/gthreadpool.c @@ -414,7 +414,7 @@ g_thread_pool_start_thread (GRealThreadPool *pool, GThread *thread; /* No thread was found, we have to start a new one */ - thread = g_thread_new ("pool", g_thread_pool_thread_proxy, pool, error); + thread = g_thread_try ("pool", g_thread_pool_thread_proxy, pool, error); if (thread == NULL) return FALSE; diff --git a/glib/tests/once.c b/glib/tests/once.c index 06e811c..b11e577 100644 --- a/glib/tests/once.c +++ b/glib/tests/once.c @@ -104,7 +104,7 @@ test_once3 (void) shared = 0; for (i = 0; i < THREADS; i++) - threads[i] = g_thread_new ("once3", thread_func, NULL, NULL); + threads[i] = g_thread_new ("once3", thread_func, NULL); for (i = 0; i < THREADS; i++) g_thread_join (threads[i]); diff --git a/glib/tests/thread.c b/glib/tests/thread.c index 4ac9374..e418d01 100644 --- a/glib/tests/thread.c +++ b/glib/tests/thread.c @@ -50,7 +50,7 @@ test_thread1 (void) GThread *thread; GError *error = NULL; - thread = g_thread_new ("test", thread1_func, NULL, &error); + thread = g_thread_try ("test", thread1_func, NULL, &error); g_assert_no_error (error); result = g_thread_join (thread); @@ -71,7 +71,7 @@ test_thread2 (void) gpointer result; GThread *thread; - thread = g_thread_new ("test", thread2_func, NULL, NULL); + thread = g_thread_new ("test", thread2_func, NULL); g_assert (g_thread_self () != thread); @@ -135,7 +135,7 @@ test_thread4 (void) g_error ("prlimit failed: %s\n", g_strerror (ret)); error = NULL; - thread = g_thread_new ("a", thread1_func, NULL, &error); + thread = g_thread_try ("a", thread1_func, NULL, &error); g_assert (thread == NULL); g_assert_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN); g_error_free (error); diff --git a/gobject/tests/dynamictests.c b/gobject/tests/dynamictests.c index 6574235..b2b2975 100644 --- a/gobject/tests/dynamictests.c +++ b/gobject/tests/dynamictests.c @@ -210,7 +210,7 @@ test_multithreaded_dynamic_type_init (void) /* create threads */ for (i = 0; i < N_THREADS; i++) { - threads[i] = g_thread_new ("test", ref_unref_thread, (gpointer) DYNAMIC_OBJECT_TYPE, NULL); + threads[i] = g_thread_new ("test", ref_unref_thread, (gpointer) DYNAMIC_OBJECT_TYPE); } /* execute threads */ diff --git a/gthread/tests/1bit-mutex.c b/gthread/tests/1bit-mutex.c index 8ee492e..c1ec41c 100644 --- a/gthread/tests/1bit-mutex.c +++ b/gthread/tests/1bit-mutex.c @@ -133,8 +133,7 @@ testcase (gconstpointer data) for (i = 0; i < THREADS; i++) threads[i] = g_thread_new ("foo", thread_func, - GINT_TO_POINTER (use_pointers), - NULL); + GINT_TO_POINTER (use_pointers)); for (i = 0; i < THREADS; i++) g_thread_join (threads[i]); diff --git a/gthread/tests/atomic.c b/gthread/tests/atomic.c index ccc9f17..a9a66ea 100644 --- a/gthread/tests/atomic.c +++ b/gthread/tests/atomic.c @@ -47,7 +47,7 @@ test_atomic (void) bucket[i] = 0; for (i = 0; i < THREADS; i++) - threads[i] = g_thread_new ("atomic", thread_func, GINT_TO_POINTER (i), NULL); + threads[i] = g_thread_new ("atomic", thread_func, GINT_TO_POINTER (i)); for (i = 0; i < THREADS; i++) g_thread_join (threads[i]); diff --git a/gthread/tests/gwakeuptest.c b/gthread/tests/gwakeuptest.c index 92eec72..c15dcdc 100644 --- a/gthread/tests/gwakeuptest.c +++ b/gthread/tests/gwakeuptest.c @@ -229,7 +229,7 @@ test_threaded (void) for (i = 0; i < NUM_THREADS; i++) { context_init (&contexts[i]); - threads[i] = g_thread_new ("test", thread_func, &contexts[i], NULL); + threads[i] = g_thread_new ("test", thread_func, &contexts[i]); } /* dispatch tokens */ diff --git a/gthread/tests/spawn-multithreaded.c b/gthread/tests/spawn-multithreaded.c index df29abd..534766b 100644 --- a/gthread/tests/spawn-multithreaded.c +++ b/gthread/tests/spawn-multithreaded.c @@ -34,18 +34,16 @@ static void multithreaded_test_run (GThreadFunc function) { int i; - GError *error = NULL; GPtrArray *threads = g_ptr_array_new (); for (i = 0; i < N_THREADS; i++) { GThread *thread; - thread = g_thread_new ("test", function, GINT_TO_POINTER (i), &error); - g_assert_no_error (error); + thread = g_thread_new ("test", function, GINT_TO_POINTER (i)); g_ptr_array_add (threads, thread); } - + for (i = 0; i < N_THREADS; i++) { gpointer ret; -- 2.7.4