[debugger] Changing how debugger handles exception when hybrid suspend is enabled...
authorThays Grazia <thaystg@gmail.com>
Wed, 23 Oct 2019 20:56:58 +0000 (17:56 -0300)
committerGitHub <noreply@github.com>
Wed, 23 Oct 2019 20:56:58 +0000 (17:56 -0300)
* Removing all fixes to fix mono/mono#15203 and mono/mono#17083, and trying a new approach to fix this mono/mono#17084, together.

The thing is when we are executing on hybrid suspend the caller is executed inside try catch in the runtime_invoke_ method that is generated. And this try catch should be ignored for the debugger exception, otherwise it's the last try catch in main thread, but should always be considered to generate the stack trace.

Fixes mono/mono#17084

* This test check the case that we were missing. On preemptive this test always runs perfectly, on Hybrid, never run well until this PR.

* Changing how call unit test.
Changing variable name.

Commit migrated from https://github.com/mono/mono/commit/8fda1738f728dec900e7a53b78fefdbbbc9e0924

src/mono/mono/mini/exceptions-amd64.c
src/mono/mono/mini/exceptions-arm.c
src/mono/mono/mini/exceptions-arm64.c
src/mono/mono/mini/exceptions-mips.c
src/mono/mono/mini/exceptions-ppc.c
src/mono/mono/mini/exceptions-s390x.c
src/mono/mono/mini/exceptions-sparc.c
src/mono/mono/mini/exceptions-x86.c
src/mono/mono/mini/mini-exceptions.c

index c301b90..d5ff063 100644 (file)
@@ -394,7 +394,7 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index 75af2d9..7edb22d 100644 (file)
@@ -168,7 +168,7 @@ mono_arm_throw_exception (MonoObject *exc, host_mgreg_t pc, host_mgreg_t sp, hos
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index 0c1778a..3cc5dc7 100644 (file)
@@ -386,7 +386,7 @@ mono_arm_throw_exception (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_regs,
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index d0a325d..6d635d3 100644 (file)
@@ -200,7 +200,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } if (preserve_ips) {
index acdf700..fc55044 100644 (file)
@@ -340,7 +340,7 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp,
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index 4dc41f2..fe5ca32 100644 (file)
@@ -268,7 +268,7 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
        
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index c84d0fc..bb84090 100644 (file)
@@ -184,7 +184,7 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gb
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else (preserve_ips) {
index f43c1d0..ac84f63 100644 (file)
@@ -477,7 +477,7 @@ mono_x86_throw_exception (host_mgreg_t *regs, MonoObject *exc,
 
        if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
                MonoException *mono_ex = (MonoException*)exc;
-               if (!rethrow) {
+               if (!rethrow && !mono_ex->caught_in_unmanaged) {
                        mono_ex->stack_trace = NULL;
                        mono_ex->trace_ips = NULL;
                } else if (preserve_ips) {
index 1854a3c..5d99310 100644 (file)
@@ -2218,7 +2218,7 @@ typedef enum {
  * return \c MONO_FIRST_PASS_CALLBACK_TO_NATIVE).
  */
 static MonoFirstPassResult
-handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception, StackFrameInfo *catch_frame, gboolean *has_perform_wait_callback_method)
+handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filter_idx, MonoJitInfo **out_ji, MonoJitInfo **out_prev_ji, MonoObject *non_exception, StackFrameInfo *catch_frame, gboolean *last_mono_wrapper_runtime_invoke)
 {
        ERROR_DECL (error);
        MonoDomain *domain = mono_domain_get ();
@@ -2242,7 +2242,7 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
        MonoFirstPassResult result = MONO_FIRST_PASS_UNHANDLED;
 
        g_assert (ctx != NULL);
-
+       *last_mono_wrapper_runtime_invoke = TRUE;
        if (obj == (MonoObject *)domain->stack_overflow_ex)
                stack_overflow = TRUE;
 
@@ -2475,8 +2475,8 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
                                                //try to find threadpool_perform_wait_callback_method
                                                unwind_res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, &new_ctx, &new_ctx, NULL, &lmf, NULL, &frame);
                                                while (unwind_res) {
-                                                       if (frame.ji && !frame.ji->is_trampoline && jinfo_get_method (frame.ji) == mono_defaults.threadpool_perform_wait_callback_method) {
-                                                               *has_perform_wait_callback_method = TRUE;
+                                                       if (frame.ji && !frame.ji->is_trampoline && jinfo_get_method (frame.ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
+                                                               *last_mono_wrapper_runtime_invoke = FALSE;
                                                                break;
                                                        }
                                                        unwind_res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, &new_ctx, &new_ctx, NULL, &lmf, NULL, &frame);
@@ -2555,6 +2555,8 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
        MonoObject *non_exception = NULL;
        Unwinder unwinder;
        gboolean in_interp;
+       gboolean is_caught_unmanaged = FALSE;
+       gboolean last_mono_wrapper_runtime_invoke = TRUE;
 
        g_assert (ctx != NULL);
        if (!obj) {
@@ -2594,6 +2596,10 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        ;
        }
 
+       if (mono_ex->caught_in_unmanaged)
+               is_caught_unmanaged = TRUE;
+       
+
        if (mono_object_isinst_checked (obj, mono_defaults.exception_class, error)) {
                mono_ex = (MonoException*)obj;
        } else {
@@ -2686,8 +2692,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
 
                StackFrameInfo catch_frame;
                MonoFirstPassResult res;
-               gboolean has_perform_wait_callback_method = FALSE;
-               res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame, &has_perform_wait_callback_method);
+               res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame, &last_mono_wrapper_runtime_invoke);
 
                if (res == MONO_FIRST_PASS_UNHANDLED) {
                        if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
@@ -2727,12 +2732,14 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                        if (unhandled)
                                mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, NULL, NULL);
                        else if (!ji || (jinfo_get_method (ji)->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE)) {
-                               if (!has_perform_wait_callback_method)
+                               if (last_mono_wrapper_runtime_invoke && mono_thread_get_main () && (mono_thread_internal_current () == mono_thread_get_main ()->internal_thread))
                                        mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, NULL, NULL);
-                               mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, &ctx_cp, &catch_frame);
+                               else
+                                       mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, &ctx_cp, &catch_frame);
                        }
                        else if (res != MONO_FIRST_PASS_CALLBACK_TO_NATIVE)
-                               mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, &ctx_cp, &catch_frame);
+                               if (!is_caught_unmanaged)
+                                       mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, &ctx_cp, &catch_frame);
                }
        }