[debugger][exception] Debugger breaks on handled exceptions (mono/mono#17106)
authorThays Grazia <thaystg@gmail.com>
Mon, 7 Oct 2019 12:22:06 +0000 (08:22 -0400)
committerGitHub <noreply@github.com>
Mon, 7 Oct 2019 12:22:06 +0000 (08:22 -0400)
* If there is a perform_wait_callback in the stack there will be another catch generated by the owner thread, so we don't need to throw, we can continue and find the next catch.
Fixes mono/mono#17083

* Reverting unit test changed on commit 405d521.

* Fixing assert when calling mono_jit_info_get_method if it was a trampoline.

Commit migrated from https://github.com/mono/mono/commit/18fac0a24190cb3f90057d86232e773758bb1284

src/mono/mono/mini/mini-exceptions.c

index 6c4c768..b12322f 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)
+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)
 {
        ERROR_DECL (error);
        MonoDomain *domain = mono_domain_get ();
@@ -2471,6 +2471,17 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
                                        frame.native_offset = (char*)ei->handler_start - (char*)ji->code_start;
                                        *catch_frame = frame;
                                        result = MONO_FIRST_PASS_HANDLED;
+                                       if (method->wrapper_type == MONO_WRAPPER_RUNTIME_INVOKE) {
+                                               //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;
+                                                               break;
+                                                       }
+                                                       unwind_res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, &new_ctx, &new_ctx, NULL, &lmf, NULL, &frame);
+                                               }
+                                       }
                                        return result;
                                }
                                mono_error_cleanup (isinst_error);
@@ -2675,7 +2686,8 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
 
                StackFrameInfo catch_frame;
                MonoFirstPassResult res;
-               res = handle_exception_first_pass (&ctx_cp, obj, &first_filter_idx, &ji, &prev_ji, non_exception, &catch_frame);
+               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);
 
                if (res == MONO_FIRST_PASS_UNHANDLED) {
                        if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
@@ -2715,7 +2727,8 @@ 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)) {
-                               mini_get_dbg_callbacks ()->handle_exception ((MonoException *)obj, ctx, NULL, NULL);
+                               if (!has_perform_wait_callback_method)
+                                       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 if (res != MONO_FIRST_PASS_CALLBACK_TO_NATIVE)