[interp] Use existing InterpMethod if allocation and lookup race (#57985)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Tue, 24 Aug 2021 19:27:13 +0000 (15:27 -0400)
committerGitHub <noreply@github.com>
Tue, 24 Aug 2021 19:27:13 +0000 (15:27 -0400)
If two threads both want to get an InterpMethod for the same MonoMethod, and
they both see null from the first hash table lookup, make sure that whichever
one comes into the jit_mm lock second re-uses the previously inserted
InterpMethod, instead of its own version.

Without this change, racing threads will overwrite
MonoJitInfo:seq_points (in mono_interp_transform_method) which sometimes leads
to deallocating the same sequence points multiple times.

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

Co-authored-by: Aleksey Kliger <alklig@microsoft.com>
src/mono/mono/mini/interp/interp.c

index 6db2f62..623b7af 100644 (file)
@@ -495,8 +495,12 @@ mono_interp_get_imethod (MonoMethod *method, MonoError *error)
                imethod->param_types [i] = mini_get_underlying_type (sig->params [i]);
 
        jit_mm_lock (jit_mm);
-       if (!mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method))
+       InterpMethod *old_imethod;
+       if (!((old_imethod = mono_internal_hash_table_lookup (&jit_mm->interp_code_hash, method))))
                mono_internal_hash_table_insert (&jit_mm->interp_code_hash, method, imethod);
+       else {
+               imethod = old_imethod; /* leak the newly allocated InterpMethod to the mempool */
+       }
        jit_mm_unlock (jit_mm);
 
        imethod->prof_flags = mono_profiler_get_call_instrumentation_flags (imethod->method);