diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c index cc883afbfb63..82232a051feb 100644 --- a/mono/mini/exceptions-amd64.c +++ b/mono/mini/exceptions-amd64.c @@ -38,10 +38,12 @@ static MonoW32ExceptionHandler fpe_handler; static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; -static LPTOP_LEVEL_EXCEPTION_FILTER old_handler; +LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; +guint64 mono_win_chained_exception_filter_result; +gboolean mono_win_chained_exception_filter_didrun; #define W32_SEH_HANDLE_EX(_ex) \ - if (_ex##_handler) _ex##_handler(0, er, sctx) + if (_ex##_handler) _ex##_handler(0, ep, sctx) /* * Unhandled Exception Filter @@ -54,6 +56,7 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) MonoContext* sctx; LONG res; + mono_win_chained_exception_filter_didrun = FALSE; res = EXCEPTION_CONTINUE_EXECUTION; er = ep->ExceptionRecord; @@ -114,17 +117,20 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) g_free (sctx); + if (mono_win_chained_exception_filter_didrun) + res = mono_win_chained_exception_filter_result; + return res; } void win32_seh_init() { - old_handler = SetUnhandledExceptionFilter(seh_handler); + mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_handler); } void win32_seh_cleanup() { - if (old_handler) SetUnhandledExceptionFilter(old_handler); + if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter); } void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c index dfbaed6de6ca..3a7314c4e606 100644 --- a/mono/mini/exceptions-x86.c +++ b/mono/mini/exceptions-x86.c @@ -39,14 +39,16 @@ static MonoW32ExceptionHandler fpe_handler; static MonoW32ExceptionHandler ill_handler; static MonoW32ExceptionHandler segv_handler; -static LPTOP_LEVEL_EXCEPTION_FILTER old_handler; +LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; +guint64 mono_win_chained_exception_filter_result; +gboolean mono_win_chained_exception_filter_didrun; #ifndef PROCESS_CALLBACK_FILTER_ENABLED # define PROCESS_CALLBACK_FILTER_ENABLED 1 #endif #define W32_SEH_HANDLE_EX(_ex) \ - if (_ex##_handler) _ex##_handler(0, er, sctx) + if (_ex##_handler) _ex##_handler(0, ep, sctx) /* * mono_win32_get_handle_stackoverflow (void): @@ -176,6 +178,7 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) struct sigcontext* sctx; LONG res; + mono_win_chained_exception_filter_didrun = FALSE; res = EXCEPTION_CONTINUE_EXECUTION; er = ep->ExceptionRecord; @@ -228,6 +231,9 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep) g_free (sctx); + if (mono_win_chained_exception_filter_didrun) + res = mono_win_chained_exception_filter_result; + return res; } @@ -237,12 +243,12 @@ void win32_seh_init() if (!restore_stack) restore_stack = mono_win32_get_handle_stackoverflow (); - old_handler = SetUnhandledExceptionFilter(seh_handler); + mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_handler); } void win32_seh_cleanup() { - if (old_handler) SetUnhandledExceptionFilter(old_handler); + if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter); } void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler) diff --git a/mono/mini/mini-windows.c b/mono/mini/mini-windows.c index 0dd21d86ee4e..8b011438e575 100644 --- a/mono/mini/mini-windows.c +++ b/mono/mini/mini-windows.c @@ -50,6 +50,10 @@ #include "jit-icalls.h" +extern LPTOP_LEVEL_EXCEPTION_FILTER mono_old_win_toplevel_exception_filter; +extern guint64 mono_win_chained_exception_filter_result; +extern gboolean mono_win_chained_exception_filter_didrun; + void mono_runtime_install_handlers (void) { @@ -71,9 +75,24 @@ mono_runtime_cleanup_handlers (void) #endif } + +/* mono_chain_signal: + * + * Call the original signal handler for the signal given by the arguments, which + * should be the same as for a signal handler. Returns TRUE if the original handler + * was called, false otherwise. + */ gboolean SIG_HANDLER_SIGNATURE (mono_chain_signal) { + int signal = _dummy; + GET_CONTEXT; + + if (mono_old_win_toplevel_exception_filter) { + mono_win_chained_exception_filter_didrun = TRUE; + mono_win_chained_exception_filter_result = (*mono_old_win_toplevel_exception_filter)(info); + return TRUE; + } return FALSE; } diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index d6965dbdd9af..9e84d1c02b97 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -6444,7 +6444,8 @@ gboolean mono_arch_is_single_step_event (void *info, void *sigctx) { #ifdef TARGET_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; /* Sometimes the address is off by 4 */ + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */ + if ((einfo->ExceptionInformation[1] >= ss_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)ss_trigger_page + 128)) return TRUE; else @@ -6463,7 +6464,7 @@ gboolean mono_arch_is_breakpoint_event (void *info, void *sigctx) { #ifdef TARGET_WIN32 - EXCEPTION_RECORD* einfo = (EXCEPTION_RECORD*)info; /* Sometimes the address is off by 4 */ + EXCEPTION_RECORD* einfo = ((EXCEPTION_POINTERS*)info)->ExceptionRecord; /* Sometimes the address is off by 4 */ if ((einfo->ExceptionInformation[1] >= bp_trigger_page && (guint8*)einfo->ExceptionInformation[1] <= (guint8*)bp_trigger_page + 128)) return TRUE; else diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index 6ebcc397fa54..6f72f209ee6e 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -31,7 +31,8 @@ struct sigcontext { unsigned int eip; }; -typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_RECORD *info, void *context); +typedef void (* MonoW32ExceptionHandler) (int _dummy, EXCEPTION_POINTERS *info, void *context); + void win32_seh_init(void); void win32_seh_cleanup(void); void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler); diff --git a/mono/mini/mini.h b/mono/mini/mini.h index 6df0fc96cdd4..2adb965728a5 100644 --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@ -2421,7 +2421,7 @@ gboolean mono_gdb_render_native_backtraces (void) MONO_INTERNAL; #define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *info, void *context) #define SIG_HANDLER_PARAMS _dummy, info, context #elif defined(HOST_WIN32) -#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_RECORD *info, void *context) +#define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *info, void *context) #define SIG_HANDLER_PARAMS _dummy, info, context #elif defined(__HAIKU__) #define SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, void *userData, vregs regs)