[interp] Switch to GC Unsafe mode before calling get_interp_to_native_trampoline...
authorAleksey Kliger (λgeek) <alklig@microsoft.com>
Mon, 1 Jun 2020 21:29:03 +0000 (17:29 -0400)
committerGitHub <noreply@github.com>
Mon, 1 Jun 2020 21:29:03 +0000 (17:29 -0400)
* [interp] Switch to GC Unsafe mode before calling get_interp_to_native_trampoline

For PInvokes, `ves_pinvoke_method` is called when we're interpreting the
pinvoke wrapper, after it already executed a transition from GC Unsafe to GC
Safe mode.  At that point, calling back into the runtime we have to temporarily
switch back to GC Unsafe mode.

Example stack trace where we don't:

```
     0x10dbdd7d6 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_dump_native_crash_info
      0x10db7f665 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_handle_native_crash
      0x10dbdcf3f - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : sigabrt_signal_handler
      0x7fff6886af5a - /usr/lib/system/libsystem_platform.dylib : _sigtramp
      0x0 - Unknown
      0x7fff686081ae - /usr/lib/system/libsystem_c.dylib : abort
      0x10dd9e887 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : monoeg_assert_abort
      0x10dd75257 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_log_write_logfile
      0x10dd9ed15 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : monoeg_g_logv_nofree
      0x10dd9edd2 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : monoeg_g_log
      0x10dd8b4fc - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_threads_transition_do_blocking
      0x10dd8cc63 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_threads_enter_gc_safe_region_unbalanced_with_info
      0x10dc40a39 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_coop_mutex_lock
      0x10dc41e05 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_domain_alloc0
      0x10dadba6f - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_tramp_info_register_internal
      0x10dbece91 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : get_interp_to_native_trampoline
      0x10dbebaf9 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : ves_pinvoke_method
      0x10dbe0e58 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : interp_exec_method
      0x10dbdf17b - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : interp_runtime_invoke
      0x10dcbae58 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_runtime_invoke_checked
      0x10dcbacf3 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_runtime_object_init_handle
      0x10dc6367f - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_exception_new_by_name_domain
      0x10dc63523 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_exception_from_name_domain
      0x10dbe81c6 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : interp_exec_method
      0x10dbdf17b - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : interp_runtime_invoke
      0x10dcbae58 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : mono_runtime_invoke_checked
      0x10dcd6e69 - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : start_wrapper_internal
      0x10dcd6b9e - /private/tmp/helix/working/B38709D8/p/libcoreclr.dylib : start_wrapper
      0x7fff68874661 - /usr/lib/system/libsystem_pthread.dylib : _pthread_body
      0x7fff6887450d - /usr/lib/system/libsystem_pthread.dylib : _pthread_body
      0x7fff68873bf9 - /usr/lib/system/libsystem_pthread.dylib : thread_start
```

src/mono/mono/mini/interp/interp.c

index 15656c8..541544f 100644 (file)
@@ -1525,8 +1525,18 @@ ves_pinvoke_method (
 
        g_assert (!frame.imethod);
 
+       /*
+        * When there's a calli in a pinvoke wrapper, we're in GC Safe mode.
+        * When we're called for some other calli, we may be in GC Unsafe mode.
+        *
+        * On any code path where we call anything other than the entry_func,
+        * we need to switch back to GC Unsafe before calling the runtime.
+        */
+       MONO_REQ_GC_NEUTRAL_MODE;
+
        static MonoPIFunc entry_func = NULL;
        if (!entry_func) {
+               MONO_ENTER_GC_UNSAFE;
 #ifdef MONO_ARCH_HAS_NO_PROPER_MONOCTX
                ERROR_DECL (error);
                entry_func = (MonoPIFunc) mono_jit_compile_method_jit_only (mini_get_interp_lmf_wrapper ("mono_interp_to_native_trampoline", (gpointer) mono_interp_to_native_trampoline), error);
@@ -1535,6 +1545,7 @@ ves_pinvoke_method (
                entry_func = get_interp_to_native_trampoline ();
 #endif
                mono_memory_barrier ();
+               MONO_EXIT_GC_UNSAFE;
        }
 
 #ifdef ENABLE_NETCORE