[threads] Enter GC Unsafe before pumping HP queue in unregister_thread (mono/mono...
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Wed, 31 Jul 2019 17:30:30 +0000 (13:30 -0400)
committerGitHub <noreply@github.com>
Wed, 31 Jul 2019 17:30:30 +0000 (13:30 -0400)
If the thread info TLS key dtor runs unregister_thread from a foreign thread
and we have work in the hazard pointer queue, we need to first switch to GC
Unsafe mode because some of the free methods passed to
mono_thread_hazardous_try_free need to be coop-aware.

Also, added checked mode assertions that conc_table_free and
jit_info_table_free are called from GC Unsafe mode.

Fixes https://github.com/mono/mono/issues/15878

Commit migrated from https://github.com/mono/mono/commit/349a3d5eef9ceaae51ef4d9d984cebab36ef0a2f

src/mono/mono/metadata/jit-info.c
src/mono/mono/metadata/mono-conc-hash.c
src/mono/mono/utils/mono-threads.c

index 2ad7d2c..8cc4f1e 100644 (file)
@@ -91,6 +91,8 @@ mono_jit_info_table_new (MonoDomain *domain)
 static void
 jit_info_table_free (MonoJitInfoTable *table, gboolean duplicate)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        int i;
        int num_chunks = table->num_chunks;
        MonoDomain *domain = table->domain;
index 4f66018..cd13110 100644 (file)
@@ -65,6 +65,8 @@ conc_table_new (MonoConcGHashTable *hash, int size)
 static void
 conc_table_free (gpointer ptr)
 {
+       MONO_REQ_GC_UNSAFE_MODE;
+
        conc_table *table = (conc_table *)ptr;
        if (table->gc_type & MONO_HASH_KEY_GC)
                mono_gc_deregister_root ((char*)table->keys);
index 1b120bb..ddce7c4 100644 (file)
@@ -522,15 +522,19 @@ unregister_thread (void *arg)
        g_assert (mono_thread_info_is_current (info));
        g_assert (mono_thread_info_is_live (info));
 
+       /* We only enter the GC unsafe region, as when exiting this function, the thread
+        * will be detached, and the current MonoThreadInfo* will be destroyed. */
+       mono_threads_enter_gc_unsafe_region_unbalanced_with_info (info, &gc_unsafe_stackdata);
+
+       /* Need to be in GC Unsafe to pump the HP queue - some of the cleanup
+        * methods need to use coop-aware locks. For example: jit_info_table_free_duplicate.
+        */
+
        /* Pump the HP queue while the thread is alive.*/
        mono_thread_hazardous_try_free_some ();
 
        small_id = info->small_id;
 
-       /* We only enter the GC unsafe region, as when exiting this function, the thread
-        * will be detached, and the current MonoThreadInfo* will be destroyed. */
-       mono_threads_enter_gc_unsafe_region_unbalanced_with_info (info, &gc_unsafe_stackdata);
-
        THREADS_DEBUG ("unregistering info %p\n", info);
 
        mono_native_tls_set_value (thread_exited_key, GUINT_TO_POINTER (1));