[threads] Allow resetting the name of a threadpool thread (#4350)
authorLudovic Henry <ludovic@xamarin.com>
Thu, 9 Feb 2017 02:12:44 +0000 (21:12 -0500)
committerGitHub <noreply@github.com>
Thu, 9 Feb 2017 02:12:44 +0000 (21:12 -0500)
Fixes bug https://bugzilla.xamarin.com/show_bug.cgi?id=47221

mcs/class/corlib/Test/System.Threading/ThreadTest.cs
mono/metadata/appdomain.c
mono/metadata/attach.c
mono/metadata/gc.c
mono/metadata/threadpool-worker-default.c
mono/metadata/threadpool.c
mono/metadata/threads-types.h
mono/metadata/threads.c
mono/mini/aot-compiler.c
mono/mini/debugger-agent.c

index 4c6694f1e17f137b4112f86e51c0081a24041b53..ae5bdbfd586d3391d656861047590897068957ca 100644 (file)
@@ -13,6 +13,7 @@ using System;
 using System.Globalization;
 using System.Security.Principal;
 using System.Threading;
+using System.Threading.Tasks;
 using System.Reflection;
 using System.Collections.Generic;
 using SD = System.Diagnostics;
@@ -908,6 +909,25 @@ namespace MonoTests.System.Threading
                }
 #endif // MONO_FEATURE_MULTIPLE_APPDOMAINS
 
+               [Test]
+               public void SetNameInThreadPoolThread ()
+               {
+                       for (int i = 0; i < 10; ++i) {
+                               Task t = Task.Run (delegate () {
+                                       Thread.CurrentThread.Name = "x/" + i;
+                                       Assert.AreEqual (Thread.CurrentThread.Name, "x/" + i, "#1");
+
+                                       try {
+                                               Thread.CurrentThread.Name = "y/" + i;
+                                               Assert.Fail ("#2");
+                                       } catch (InvalidOperationException) {
+                                       }
+                               });
+
+                               t.Wait ();
+                       }
+               }
+
                void CheckIsRunning (string s, Thread t)
                {
                        int c = counter;
index 921aa7e2d611a2191140f50efce4bb772f8da35a..819ce65616e9a93d8628e0b5a39c55ce0b0a06de 100644 (file)
@@ -2486,7 +2486,7 @@ unload_thread_main (void *arg)
        /* Force it to be attached to avoid racing during shutdown. */
        thread = mono_thread_attach_full (mono_get_root_domain (), TRUE);
 
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Domain unloader"), TRUE, &error);
+       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Domain unloader"), TRUE, FALSE, &error);
        if (!is_ok (&error)) {
                data->failure_reason = g_strdup (mono_error_get_message (&error));
                mono_error_cleanup (&error);
index d7c39797a66a6e6e623f5b43c9ef76ccc8c09aad..1f2e0fd103d93fc73768878b4f0c3181f40de996 100644 (file)
@@ -506,7 +506,7 @@ receiver_thread (void *arg)
                printf ("attach: Connected.\n");
 
                MonoThread *thread = mono_thread_attach (mono_get_root_domain ());
-               mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Attach receiver"), TRUE, &error);
+               mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Attach receiver"), TRUE, FALSE, &error);
                mono_error_assert_ok (&error);
                /* Ask the runtime to not abort this thread */
                //mono_thread_current ()->flags |= MONO_THREAD_FLAG_DONT_MANAGE;
index fecd120d419974d27701298ab5b5b700c215c3e4..ffe0fd3a5cfd4eb6b53a43b2c388b1a2d44bd796 100644 (file)
@@ -888,7 +888,7 @@ finalizer_thread (gpointer unused)
        MonoError error;
        gboolean wait = TRUE;
 
-       mono_thread_set_name_internal (mono_thread_internal_current (), mono_string_new (mono_get_root_domain (), "Finalizer"), FALSE, &error);
+       mono_thread_set_name_internal (mono_thread_internal_current (), mono_string_new (mono_get_root_domain (), "Finalizer"), FALSE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        /* Register a hazard free queue pump callback */
index 6c499ebac9b2f9bead737848bf52ded8420036b6..6e3a4b52130246a4f2a1d63fe02b3f443e51bca6 100644 (file)
@@ -546,7 +546,6 @@ static gsize WINAPI
 worker_thread (gpointer data)
 {
        MonoThreadPoolWorker *worker;
-       MonoError error;
        MonoInternalThread *thread;
        ThreadPoolWorkerCounter counter;
 
@@ -567,9 +566,6 @@ worker_thread (gpointer data)
        g_ptr_array_add (worker->threads, thread);
        mono_coop_mutex_unlock (&worker->threads_lock);
 
-       mono_thread_set_name_internal (thread, mono_string_new (mono_get_root_domain (), "Threadpool worker"), FALSE, &error);
-       mono_error_assert_ok (&error);
-
        while (!mono_runtime_is_shutting_down ()) {
                ThreadPoolWorkItem work_item;
 
index e58a78d47e0e37e9669762067b68316268d9caf5..c1f0c1a12a9f233f0dc41f902b60d7d2c6570abf 100644 (file)
@@ -422,6 +422,9 @@ worker_callback (gpointer unused)
 
                domains_unlock ();
 
+               mono_thread_set_name_internal (thread, mono_string_new (mono_get_root_domain (), "Threadpool worker"), FALSE, TRUE, &error);
+               mono_error_assert_ok (&error);
+
                mono_thread_clr_state (thread, (MonoThreadState)~ThreadState_Background);
                if (!mono_thread_test_state (thread , ThreadState_Background))
                        ves_icall_System_Threading_Thread_SetState (thread, ThreadState_Background);
index c473777932a32d97d7ba6899877ebacff9b6fff4..b562d2c850502b9edc67cd390d1978b5f32c59a7 100644 (file)
@@ -202,7 +202,7 @@ gunichar2* mono_thread_get_name (MonoInternalThread *this_obj, guint32 *name_len
 
 MONO_API MonoException* mono_thread_get_undeniable_exception (void);
 
-void mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, MonoError *error);
+void mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, gboolean reset, MonoError *error);
 
 void mono_thread_suspend_all_other_threads (void);
 gboolean mono_threads_abort_appdomain_threads (MonoDomain *domain, int timeout);
index b94a4ff7ff3a96bc0425f137514931e03b118acc..fe4365c29ba9a33999ae99de23761190997aa13b 100644 (file)
@@ -1569,13 +1569,15 @@ ves_icall_System_Threading_Thread_GetName_internal (MonoInternalThread *this_obj
 }
 
 void 
-mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, MonoError *error)
+mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, gboolean permanent, gboolean reset, MonoError *error)
 {
        LOCK_THREAD (this_obj);
 
        mono_error_init (error);
 
-       if ((this_obj->flags & MONO_THREAD_FLAG_NAME_SET)) {
+       if (reset) {
+               this_obj->flags &= ~MONO_THREAD_FLAG_NAME_SET;
+       } else if (this_obj->flags & MONO_THREAD_FLAG_NAME_SET) {
                UNLOCK_THREAD (this_obj);
                
                mono_error_set_invalid_operation (error, "Thread.Name can only be set once.");
@@ -1586,8 +1588,7 @@ mono_thread_set_name_internal (MonoInternalThread *this_obj, MonoString *name, g
                this_obj->name_len = 0;
        }
        if (name) {
-               this_obj->name = g_new (gunichar2, mono_string_length (name));
-               memcpy (this_obj->name, mono_string_chars (name), mono_string_length (name) * 2);
+               this_obj->name = g_memdup (mono_string_chars (name), mono_string_length (name) * sizeof (gunichar2));
                this_obj->name_len = mono_string_length (name);
 
                if (permanent)
@@ -1612,7 +1613,7 @@ void
 ves_icall_System_Threading_Thread_SetName_internal (MonoInternalThread *this_obj, MonoString *name)
 {
        MonoError error;
-       mono_thread_set_name_internal (this_obj, name, TRUE, &error);
+       mono_thread_set_name_internal (this_obj, name, TRUE, FALSE, &error);
        mono_error_set_pending_exception (&error);
 }
 
index 701364be006eb4776bc2a7e94ba4ad1ebf8e7077..6e91638d881fe1f3f3f97a4cf2c9d97e12c9555b 100644 (file)
@@ -7897,7 +7897,7 @@ compile_thread_main (gpointer user_data)
 
        MonoError error;
        MonoThread *thread = mono_thread_attach (domain);
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "AOT compiler"), TRUE, &error);
+       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "AOT compiler"), TRUE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        for (i = 0; i < methods->len; ++i)
index 11b7125b2b379a37c6acf4692320f992e8dfaa99..541b26e160a60bcffcdd4db5f8beb030f26a40fb 100644 (file)
@@ -10137,7 +10137,7 @@ debugger_thread (void *arg)
        debugger_thread_id = mono_native_thread_id_get ();
 
        MonoThread *thread = mono_thread_attach (mono_get_root_domain ());
-       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Debugger agent"), TRUE, &error);
+       mono_thread_set_name_internal (thread->internal_thread, mono_string_new (mono_get_root_domain (), "Debugger agent"), TRUE, FALSE, &error);
        mono_error_assert_ok (&error);
 
        thread->internal_thread->state |= ThreadState_Background;