[interp] avoid exception checkpoint when in thread is in GC Safe state (mono/mono...
authorBernhard Urban <lewurm@gmail.com>
Fri, 20 Sep 2019 20:15:55 +0000 (22:15 +0200)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Fri, 20 Sep 2019 20:15:55 +0000 (22:15 +0200)
[interp] avoid exception checkpoint when in thread is in GC Safe state

Usually the interpreter operates in GC Unsafe state. There is an exception however, and that is when it executes a `managed-to-native` wrapper in cooperative (or hybrid) suspend.

The wrapper does essentially:
1. enter GC Safe state via `mono_threads_enter_gc_safe_region_unbalanced`
2. call native function
3. exit GC state via `mono_threads_exit_gc_safe_region_unbalanced`

Usually upon return of a native function call, the interpreter would check for thread interruption and, if applicable, throw an exception.  That, however, would mess with the GC state as the interpreter operates in GC Safe state at this moment.

Note that ignoring thread interruption at that point shouldn't be a problem, because after 3. the `managed-to-native` wrapper will check for thread interruption anyway.

Contributes to https://github.com/mono/mono/issues/16819

Commit migrated from https://github.com/mono/mono/commit/e27159174a017efb3ebc66c9c66fc1785c4bd930

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

index b41d4ca..5eb95af 100644 (file)
@@ -3483,7 +3483,8 @@ main_loop:
                        frame->ip = ip;
 
                        sp = do_icall_wrapper (frame, csignature, opcode, sp, target_ip, save_last_error);
-                       EXCEPTION_CHECKPOINT;
+                       if (mono_thread_is_gc_unsafe_mode ()) /* do not enter EH in GC Safe state */
+                               EXCEPTION_CHECKPOINT;
                        CHECK_RESUME_STATE (context);
                        ip += 4;
                        MINT_IN_BREAK;
@@ -5926,7 +5927,8 @@ common_vcall:
                MINT_IN_CASE(MINT_ICALL_PPPPPP_P)
                        frame->ip = ip;
                        sp = do_icall_wrapper (frame, NULL, *ip, sp, frame->imethod->data_items [ip [1]], FALSE);
-                       EXCEPTION_CHECKPOINT;
+                       if (mono_thread_is_gc_unsafe_mode ()) /* do not enter EH in GC Safe state */
+                               EXCEPTION_CHECKPOINT;
                        CHECK_RESUME_STATE (context);
                        ip += 2;
                        MINT_IN_BREAK;