[Mono] Don't set thread name of main thread on Linux (#36116)
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Thu, 14 May 2020 19:57:32 +0000 (15:57 -0400)
committerGitHub <noreply@github.com>
Thu, 14 May 2020 19:57:32 +0000 (15:57 -0400)
* [mono] Record MonoNativeThreadId of the main thread

We would like to know the MonoNativeThreadId (pthread_t on Linux) of the main
thread of the application.  We can identify the main thread (on linux) because
it is the one for which `gettid () == getpid ()`.  (`gettid()` returns a
`pid_t` which is not the same thing as a `pthread_t`, hence this roundabout way
of detecting it.)

A complication arises in embedding scenarios: the main thread is not
necessarily the one that calls `mono_jit_init` or otherwise interacts with the
runtime.  Therefore we do the `gettid() == getpid ()` test at `MonoThreadInfo`
creation time when we call `register_thread`.

If the main thread never interacts with Mono, the main thread is not known to
us.

* [mono] Don't set name of main thread on Linux

Setting the name of the main thread also changes the name of the process.

Fixes https://github.com/dotnet/runtime/issues/35908

The corresponding fix for CoreCLR is https://github.com/dotnet/runtime/pull/34064

* Re-enable test from https://github.com/dotnet/runtime/pull/34064

src/libraries/System.Threading.Thread/tests/ThreadTests.cs
src/mono/mono/utils/mono-threads-posix.c
src/mono/mono/utils/mono-threads.c
src/mono/mono/utils/mono-threads.h

index 7976295..97356a4 100644 (file)
@@ -652,7 +652,6 @@ namespace System.Threading.Threads.Tests
         }
 
         [Fact]
-        [ActiveIssue ("https://github.com/dotnet/runtime/issues/35908", TestRuntimes.Mono)]
         public static void ThreadNameDoesNotAffectProcessName()
         {
             // On Linux, changing the main thread name affects ProcessName.
index 61d31fd..c3ddb64 100644 (file)
@@ -308,6 +308,15 @@ mono_native_thread_set_name (MonoNativeThreadId tid, const char *name)
                pthread_setname_np (tid, "%s", (void*)n);
        }
 #elif defined (HAVE_PTHREAD_SETNAME_NP)
+#if defined (__linux__)
+       /* Ignore requests to set the main thread name because it causes the
+        * value returned by Process.ProcessName to change.
+        */
+       MonoNativeThreadId main_thread_tid;
+       if (mono_native_thread_id_main_thread_known (&main_thread_tid) &&
+           mono_native_thread_id_equals (tid, main_thread_tid))
+               return;
+#endif
        if (!name) {
                pthread_setname_np (tid, "");
        } else {
index a4cec2c..8fb5dee 100644 (file)
@@ -442,6 +442,53 @@ thread_handle_destroy (gpointer data)
        g_free (thread_handle);
 }
 
+static gboolean native_thread_id_main_thread_known;
+static MonoNativeThreadId native_thread_id_main_thread;
+
+/**
+ * mono_native_thread_id_main_thread_known:
+ *
+ * If the main thread of the process has interacted with Mono (in the sense
+ * that it has a MonoThreadInfo associated with it), return \c TRUE and write
+ * its MonoNativeThreadId to \c main_thread_tid.
+ *
+ * Otherwise return \c FALSE.
+ */
+gboolean
+mono_native_thread_id_main_thread_known (MonoNativeThreadId *main_thread_tid)
+{
+       if (!native_thread_id_main_thread_known)
+               return FALSE;
+       g_assert (main_thread_tid);
+       *main_thread_tid = native_thread_id_main_thread;
+       return TRUE;
+}
+
+/*
+ * Saves the MonoNativeThreadId (on Linux pthread_t) of the current thread if
+ * it is the main thread.
+ *
+ * The main thread is (on Linux) the one whose OS thread id (on Linux pid_t) is
+ * equal to the process id.
+ *
+ * We have to do this at thread registration time because in embedding
+ * scenarios we can't count on the main thread to be the one that calls
+ * mono_jit_init, or other runtime initialization functions.
+ */
+static void
+native_thread_set_main_thread (void)
+{
+       if (native_thread_id_main_thread_known)
+               return;
+#if defined(__linux__)
+       if (mono_native_thread_os_id_get () == (guint64)getpid ()) {
+               native_thread_id_main_thread = mono_native_thread_id_get ();
+               mono_memory_barrier ();
+               native_thread_id_main_thread_known = TRUE;
+       }
+#endif
+}
+
 static gboolean
 register_thread (MonoThreadInfo *info)
 {
@@ -451,6 +498,7 @@ register_thread (MonoThreadInfo *info)
 
        info->small_id = mono_thread_info_register_small_id ();
        mono_thread_info_set_tid (info, mono_native_thread_id_get ());
+       native_thread_set_main_thread ();
 
        info->handle = g_new0 (MonoThreadHandle, 1);
        mono_refcount_init (info->handle, thread_handle_destroy);
index a949b42..c47a33d 100644 (file)
@@ -643,6 +643,9 @@ void mono_threads_coop_end_global_suspend (void);
 MONO_API MonoNativeThreadId
 mono_native_thread_id_get (void);
 
+gboolean
+mono_native_thread_id_main_thread_known (MonoNativeThreadId *main_thread_tid);
+
 /*
  * This does _not_ return the same value as mono_native_thread_id_get, except on Windows.
  * On POSIX, mono_native_thread_id_get returns the value from pthread_self, which is then