[coop] Throw exception from finally clause in native-to-managed wrapper
authorLudovic Henry <ludovic@xamarin.com>
Mon, 9 May 2016 15:57:51 +0000 (11:57 -0400)
committerLudovic Henry <ludovic@xamarin.com>
Mon, 16 May 2016 14:57:02 +0000 (10:57 -0400)
If we do not throw it from the finally clause, then in case of a Thread.Abort, we will not rethrow the catched exception, but the ThreadAbortException, and this without using the callback, leading to native stack unwinding.

mono/metadata/marshal.c

index fe7b720a15da11e65923438c61b01413cef9dff9..e1fa7ec89a4499414b2ac10aeabc0b1b9dec289d 100644 (file)
@@ -7985,9 +7985,10 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
         *   ex = mono_gchandle_new (e, false);
         * } finally {
         *   mono_jit_detach ();
+        *
+        *   if (ex != -1)
+        *     mono_marshal_ftnptr_eh_callback (ex);
         * }
-        * if (ex != -1)
-        *   mono_marshal_ftnptr_eh_callback (ex);
         *
         * return ret;
         */
@@ -8165,7 +8166,9 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
 
        leave_try_pos = mono_mb_emit_branch (mb, CEE_LEAVE);
 
-       /* } catch (Exception e) { */
+       /* } [endtry] */
+
+       /* catch (Exception e) { */
        clause_catch->try_len = mono_mb_get_label (mb) - clause_catch->try_offset;
        clause_catch->handler_offset = mono_mb_get_label (mb);
 
@@ -8193,7 +8196,7 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        /* } [endcatch] */
        clause_catch->handler_len = mono_mb_get_pos (mb) - clause_catch->handler_offset;
 
-       /* finally { */
+       /* finally { */
        clause_finally->try_len = mono_mb_get_label (mb) - clause_finally->try_offset;
        clause_finally->handler_offset = mono_mb_get_label (mb);
 
@@ -8205,14 +8208,6 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
        mono_mb_emit_byte (mb, CEE_MONO_JIT_DETACH);
 
-       mono_mb_emit_byte (mb, CEE_ENDFINALLY);
-
-       /* } [endfinally] */
-       clause_finally->handler_len = mono_mb_get_pos (mb) - clause_finally->handler_offset;
-
-       mono_mb_patch_branch (mb, leave_try_pos);
-       mono_mb_patch_branch (mb, leave_catch_pos);
-
        /* if (ex != -1) */
        mono_mb_emit_ldloc (mb, ex_local);
        mono_mb_emit_icon (mb, -1);
@@ -8226,6 +8221,14 @@ mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *i
        /* [ex == -1] */
        mono_mb_patch_branch (mb, ex_m1_pos);
 
+       mono_mb_emit_byte (mb, CEE_ENDFINALLY);
+
+       /* } [endfinally] */
+       clause_finally->handler_len = mono_mb_get_pos (mb) - clause_finally->handler_offset;
+
+       mono_mb_patch_branch (mb, leave_try_pos);
+       mono_mb_patch_branch (mb, leave_catch_pos);
+
        /* return ret; */
        if (m->retobj_var) {
                mono_mb_emit_ldloc (mb, m->retobj_var);