summaryrefslogtreecommitdiff
path: root/rts/win32/seh_excn.h
diff options
context:
space:
mode:
authorIan Lynagh <igloo@earth.li>2007-08-24 22:23:17 +0000
committerIan Lynagh <igloo@earth.li>2007-08-24 22:23:17 +0000
commit49b8105e8d56c90099234e31c32ba3f1643276fe (patch)
tree01d11dff9c5afd8daf3bfd9a021b9c8848f28223 /rts/win32/seh_excn.h
parent32f2ee11b7288a53b89ea81ebdf4f8a74b707fed (diff)
downloadhaskell-49b8105e8d56c90099234e31c32ba3f1643276fe.tar.gz
Jump through some hoops to make the Windows SEH exception stuff happy
Diffstat (limited to 'rts/win32/seh_excn.h')
-rw-r--r--rts/win32/seh_excn.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/rts/win32/seh_excn.h b/rts/win32/seh_excn.h
new file mode 100644
index 0000000000..410d430871
--- /dev/null
+++ b/rts/win32/seh_excn.h
@@ -0,0 +1,91 @@
+#ifndef __SEH_EXCN_H__
+#define __SEH_EXCN_H__
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(__MINGW32__)
+/* Stuff needed to install and use SEH exception handlers */
+#include <excpt.h>
+#include <setjmp.h>
+#include <windows.h>
+#elif defined(_MSC_VER)
+#include <windows.h>
+#else
+#include <signal.h>
+#endif
+
+/* Exception handling.
+ *
+ * On Win32, the default action for things like division by zero and
+ * segfaults is to pop up an annoying little dialog box.
+ *
+ * This is a pain when we are SSHed into a Windows machine, or when we
+ * want to debug a problem with gdb.
+ *
+ * seh_excn provides two macros, BEGIN_CATCH and END_CATCH, which
+ * will catch such exceptions in the code they bracket and die by
+ * printing a message and calling exit(1).
+ */
+#define ON_DIV_ZERO fprintf(stdout,"divide by zero\n"); fflush(stdout);exit(1)
+#define ON_STACK_OVERFLOW fprintf(stdout,"C stack overflow in generated code\n"); fflush(stdout); exit(1)
+#define ON_SIGSEGV fprintf(stdout,"Segmentation fault/access violation in generated code\n"); fflush(stdout); exit(1)
+
+#if defined(__MINGW32__)
+extern jmp_buf seh_unwind_to;
+extern unsigned long seh_excn_code;
+/*
+ * install an exception handler 'exHandler' which longjmp()s (via 'jumpBuf')
+ * to the code 'onExnCaught' when successfully catching an exception.
+ *
+ * Macro based on Andrew Begel's SEH support code posted to the mingw-users
+ * mailing list.
+ */
+#define TRY_BEGIN(jumpBuf, exHandler, onExcnCaught) \
+ do { \
+ int signal; \
+ if ((signal = setjmp(jumpBuf)) != 0) { \
+ onExcnCaught; \
+ } else { \
+ __try1(exHandler); \
+ } \
+ } while (0);
+
+#define TRY_END() __except1
+
+extern
+EXCEPTION_DISPOSITION
+catchDivZero(struct _EXCEPTION_RECORD*,
+ void*,
+ struct _CONTEXT*,
+ void*);
+
+#define ON_EXCN \
+ if (seh_excn_code == 1) { \
+ ON_STACK_OVERFLOW; \
+ } else if ( seh_excn_code == 2 ) { \
+ ON_SIGSEGV; \
+ } else { \
+ ON_DIV_ZERO; \
+ }
+
+#define BEGIN_CATCH TRY_BEGIN(seh_unwind_to, catchDivZero, ON_EXCN)
+#define END_CATCH TRY_END()
+#elif defined(_MSC_VER)
+#define BEGIN_CATCH __try {
+#define END_CATCH } __except ( ( ((GetExceptionCode() == EXCEPTION_FLT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_INT_DIVIDE_BY_ZERO) || (GetExceptionCode() == EXCEPTION_STACK_OVERFLOW) || (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)) ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH ) ) { \
+ switch ( (GetExceptionCode()) ) { \
+ case EXCEPTION_FLT_DIVIDE_BY_ZERO: \
+ case EXCEPTION_INT_DIVIDE_BY_ZERO:
+ ON_DIV_ZERO; break; \
+ case EXCEPTION_STACK_OVERFLOW: \
+ ON_STACK_OVERFLOW; break; \
+ case EXCEPTION_ACCESS_VIOLATION: \
+ ON_SIGSEGV; break; \
+ } \
+ }
+#else
+#error Don't know what sort of Windows system this is
+#endif
+
+#endif /* __SEH_EXCN_H__ */
+