[coop] Temporarily restore MonoThreadInfo when TLS destructor runs. Fixes #43099
[mono.git] / mono / utils / mono-threads.c
index 23a3e759815e66268a5b2504f2ba32e62f23ea6e..33796525b90bec8fca74b00d013382cf4eec6398 100644 (file)
@@ -402,6 +402,8 @@ unregister_thread (void *arg)
 
        info = (MonoThreadInfo *) arg;
        g_assert (info);
+       g_assert (mono_thread_info_is_current (info));
+       g_assert (mono_thread_info_is_live (info));
 
        small_id = info->small_id;
 
@@ -637,6 +639,20 @@ mono_thread_info_is_exiting (void)
        return FALSE;
 }
 
+#ifndef HOST_WIN32
+static void
+thread_info_key_dtor (void *arg)
+{
+       /* Put the MonoThreadInfo back for the duration of the
+        * unregister code.  In some circumstances the thread needs to
+        * take the GC lock which may block which requires a coop
+        * state transition. */
+       mono_native_tls_set_value (thread_info_key, arg);
+       unregister_thread (arg);
+       mono_native_tls_set_value (thread_info_key, NULL);
+}
+#endif
+
 void
 mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
 {
@@ -648,7 +664,7 @@ mono_threads_init (MonoThreadInfoCallbacks *callbacks, size_t info_size)
        res = mono_native_tls_alloc (&thread_info_key, NULL);
        res = mono_native_tls_alloc (&thread_exited_key, NULL);
 #else
-       res = mono_native_tls_alloc (&thread_info_key, (void *) unregister_thread);
+       res = mono_native_tls_alloc (&thread_info_key, (void *) thread_info_key_dtor);
        res = mono_native_tls_alloc (&thread_exited_key, (void *) thread_exited_dtor);
 #endif
 
@@ -1026,6 +1042,8 @@ static void
 mono_thread_info_suspend_lock_with_info (MonoThreadInfo *info)
 {
        g_assert (info);
+       g_assert (mono_thread_info_is_current (info));
+       g_assert (mono_thread_info_is_live (info));
 
        MONO_ENTER_GC_SAFE_WITH_INFO(info);