*/
#include <config.h>
+
+#if _WIN32_WINNT < 0x0501
+/* Required for Vectored Exception Handling. */
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif /* _WIN32_WINNT < 0x0501 */
+
#include <glib.h>
#include <signal.h>
#include <string.h>
static MonoW32ExceptionHandler segv_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;
+gpointer mono_win_vectored_exception_handle;
+extern gboolean mono_win_chained_exception_needs_run;
+extern int (*gUnhandledExceptionHandler)(EXCEPTION_POINTERS*);
#ifndef PROCESS_CALLBACK_FILTER_ENABLED
# define PROCESS_CALLBACK_FILTER_ENABLED 1
#define W32_SEH_HANDLE_EX(_ex) \
if (_ex##_handler) _ex##_handler(0, ep, sctx)
+LONG CALLBACK seh_unhandled_exception_filter(EXCEPTION_POINTERS* ep)
+{
+#ifndef MONO_CROSS_COMPILE
+ if (mono_old_win_toplevel_exception_filter) {
+ return (*mono_old_win_toplevel_exception_filter)(ep);
+ }
+#endif
+
+ mono_handle_native_sigsegv (SIGSEGV, NULL);
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
/*
* mono_win32_get_handle_stackoverflow (void):
*
* Unhandled Exception Filter
* Top-level per-process exception handler.
*/
-LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep)
+LONG CALLBACK seh_vectored_exception_handler(EXCEPTION_POINTERS* ep)
{
EXCEPTION_RECORD* er;
CONTEXT* ctx;
struct sigcontext* sctx;
LONG res;
- mono_win_chained_exception_filter_didrun = FALSE;
+ mono_win_chained_exception_needs_run = FALSE;
res = EXCEPTION_CONTINUE_EXECUTION;
er = ep->ExceptionRecord;
break;
}
- /* Copy context back */
- ctx->Eax = sctx->eax;
- ctx->Ebx = sctx->ebx;
- ctx->Ecx = sctx->ecx;
- ctx->Edx = sctx->edx;
- ctx->Ebp = sctx->ebp;
- ctx->Esp = sctx->esp;
- ctx->Esi = sctx->esi;
- ctx->Edi = sctx->edi;
- ctx->Eip = sctx->eip;
-
- g_free (sctx);
+ if (mono_win_chained_exception_needs_run) {
+ /* Don't copy context back if we chained exception
+ * as the handler may have modfied the EXCEPTION_POINTERS
+ * directly. We don't pass sigcontext to chained handlers.
+ * Return continue search so the UnhandledExceptionFilter
+ * can correctly chain the exception.
+ */
+ res = EXCEPTION_CONTINUE_SEARCH;
+ } else {
+ /* Copy context back */
+ ctx->Eax = sctx->eax;
+ ctx->Ebx = sctx->ebx;
+ ctx->Ecx = sctx->ecx;
+ ctx->Edx = sctx->edx;
+ ctx->Ebp = sctx->ebp;
+ ctx->Esp = sctx->esp;
+ ctx->Esi = sctx->esi;
+ ctx->Edi = sctx->edi;
+ ctx->Eip = sctx->eip;
+ }
- if (mono_win_chained_exception_filter_didrun)
- res = mono_win_chained_exception_filter_result;
+ /* TODO: Find right place to free this in stack overflow case */
+ if (er->ExceptionCode != EXCEPTION_STACK_OVERFLOW)
+ g_free (sctx);
return res;
}
if (!restore_stack)
restore_stack = mono_win32_get_handle_stackoverflow ();
- mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_handler);
+ mono_old_win_toplevel_exception_filter = SetUnhandledExceptionFilter(seh_unhandled_exception_filter);
+ mono_win_vectored_exception_handle = AddVectoredExceptionHandler (1, seh_vectored_exception_handler);
}
void win32_seh_cleanup()
{
if (mono_old_win_toplevel_exception_filter) SetUnhandledExceptionFilter(mono_old_win_toplevel_exception_filter);
+ RemoveVectoredExceptionHandler (seh_unhandled_exception_filter);
}
void win32_seh_set_handler(int type, MonoW32ExceptionHandler handler)