FIX #2398: file locking wasn't thread-safe
[ghc-hetmet.git] / rts / win32 / seh_excn.h
1 #ifndef __SEH_EXCN_H__
2 #define __SEH_EXCN_H__
3 #include <stdio.h>
4 #include <stdlib.h>
5
6 #if defined(__MINGW32__)
7 /* Stuff needed to install and use SEH exception handlers */
8 #include <excpt.h>
9 #include <setjmp.h>
10 #include <windows.h>
11 #elif defined(_MSC_VER)
12 #include <windows.h>
13 #else
14 #include <signal.h>
15 #endif
16
17 /* Exception handling.
18  *
19  * On Win32, the default action for things like division by zero and
20  * segfaults is to pop up an annoying little dialog box.
21  *
22  * This is a pain when we are SSHed into a Windows machine, or when we
23  * want to debug a problem with gdb.
24  *
25  * seh_excn provides two macros, BEGIN_CATCH and END_CATCH, which
26  * will catch such exceptions in the code they bracket and die by
27  * printing a message and calling exit(1).
28  */
29 #define ON_DIV_ZERO fprintf(stdout,"divide by zero\n"); fflush(stdout);exit(1)
30 #define ON_STACK_OVERFLOW fprintf(stdout,"C stack overflow in generated code\n"); fflush(stdout); exit(1)
31 #define ON_SIGSEGV fprintf(stdout,"Segmentation fault/access violation in generated code\n"); fflush(stdout); exit(1)
32
33 #if defined(__MINGW32__)
34 extern jmp_buf seh_unwind_to;
35 extern unsigned long seh_excn_code;
36 /*
37  * install an exception handler 'exHandler' which longjmp()s (via 'jumpBuf')
38  * to the code 'onExnCaught' when successfully catching an exception.
39  *
40  * Macro based on Andrew Begel's SEH support code posted to the mingw-users
41  * mailing list.
42  */
43 #define TRY_BEGIN(jumpBuf, exHandler, onExcnCaught)  \
44     do { \
45       int signal; \
46       if ((signal = setjmp(jumpBuf)) != 0) { \
47         onExcnCaught; \
48       } else { \
49         __try1(exHandler); \
50       } \
51     } while (0);
52
53 #define TRY_END()  __except1
54
55 extern
56 EXCEPTION_DISPOSITION
57 catchDivZero(struct _EXCEPTION_RECORD*,
58          void*,
59          struct _CONTEXT*,
60          void*);
61
62 #define ON_EXCN \
63    if (seh_excn_code == 1) { \
64       ON_STACK_OVERFLOW; \
65    } else if ( seh_excn_code == 2 ) { \
66       ON_SIGSEGV; \
67    } else { \
68       ON_DIV_ZERO; \
69    }
70
71 #define BEGIN_CATCH TRY_BEGIN(seh_unwind_to, catchDivZero, ON_EXCN)
72 #define END_CATCH TRY_END()
73 #elif defined(_MSC_VER)
74 #define BEGIN_CATCH __try {
75 #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 ) ) { \
76    switch ( (GetExceptionCode()) ) { \
77     case EXCEPTION_FLT_DIVIDE_BY_ZERO: \
78     case EXCEPTION_INT_DIVIDE_BY_ZERO:
79           ON_DIV_ZERO; break; \
80     case EXCEPTION_STACK_OVERFLOW: \
81         ON_STACK_OVERFLOW; break; \
82     case EXCEPTION_ACCESS_VIOLATION: \
83         ON_SIGSEGV; break; \
84    } \
85   }
86 #else
87 #error Don't know what sort of Windows system this is
88 #endif
89
90 #endif /* __SEH_EXCN_H__ */
91