From 7c0ee79e348cfa3711ecf74f1c0e4d9a2e29864e Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Mon, 14 Nov 2011 22:18:13 -0500 Subject: [PATCH] GThread: handle thread names safely Avoid a race condition where the string may be freed before the new thread got around to using it. Also add a test for thread names. https://bugzilla.gnome.org/show_bug.cgi?id=663381 --- glib/gthread.c | 13 +++++++++---- glib/gthreadprivate.h | 2 +- glib/tests/thread.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/glib/gthread.c b/glib/gthread.c index b17280f82..d956308b3 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -57,6 +57,7 @@ #endif /* G_OS_WIN32 */ #include "gslice.h" +#include "gstrfuncs.h" #include "gtestutils.h" /** @@ -781,9 +782,6 @@ g_thread_proxy (gpointer data) g_assert (data); - if (thread->name) - g_system_thread_set_name (thread->name); - /* This has to happen before G_LOCK, as that might call g_thread_self */ g_private_set (&g_thread_specific_private, data); @@ -793,6 +791,13 @@ g_thread_proxy (gpointer data) G_LOCK (g_thread_new); G_UNLOCK (g_thread_new); + if (thread->name) + { + g_system_thread_set_name (thread->name); + g_free (thread->name); + thread->name = NULL; + } + thread->retval = thread->thread.func (thread->thread.data); return NULL; @@ -886,7 +891,7 @@ g_thread_new_internal (const gchar *name, thread->thread.joinable = TRUE; thread->thread.func = func; thread->thread.data = data; - thread->name = name; + thread->name = g_strdup (name); } G_UNLOCK (g_thread_new); diff --git a/glib/gthreadprivate.h b/glib/gthreadprivate.h index 3670b2f19..6b974debb 100644 --- a/glib/gthreadprivate.h +++ b/glib/gthreadprivate.h @@ -32,7 +32,7 @@ struct _GRealThread gint ref_count; gboolean ours; - const gchar *name; + gchar *name; gpointer retval; }; diff --git a/glib/tests/thread.c b/glib/tests/thread.c index a614c2792..b6bb5a9f9 100644 --- a/glib/tests/thread.c +++ b/glib/tests/thread.c @@ -29,6 +29,10 @@ #ifdef HAVE_UNISTD_H #include #endif +#ifdef HAVE_SYS_PRCTL_H +#include +#endif + #include @@ -160,6 +164,29 @@ test_thread5 (void) g_thread_unref (thread); } +static gpointer +thread6_func (gpointer data) +{ + const gchar name[16]; + +#ifdef HAVE_SYS_PRCTL_H + prctl (PR_GET_NAME, name, 0, 0, 0, 0); + + g_assert_cmpstr (name, ==, (gchar*)data); +#endif + + return NULL; +} + +static void +test_thread6 (void) +{ + GThread *thread; + + thread = g_thread_new ("abc", thread6_func, "abc"); + g_thread_join (thread); +} + int main (int argc, char *argv[]) { @@ -170,6 +197,7 @@ main (int argc, char *argv[]) g_test_add_func ("/thread/thread3", test_thread3); g_test_add_func ("/thread/thread4", test_thread4); g_test_add_func ("/thread/thread5", test_thread5); + g_test_add_func ("/thread/thread6", test_thread6); return g_test_run (); }