blob: c94dc5a8302d872a82fae6bbbde09ae7ecc6c8c9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
/* -----------------------------------------------------------------------------
*
* (c) The GHC Team 1998-2000
*
* Error Handling implementations for windows
*
* ---------------------------------------------------------------------------*/
#include "Rts.h"
#include "ghcconfig.h"
#include "veh_excn.h"
#include <assert.h>
/////////////////////////////////
// Exception / signal handlers.
/////////////////////////////////
// Define some values for the ordering of VEH Handlers:
// - CALL_FIRST means call this exception handler first
// - CALL_LAST means call this exception handler last
#define CALL_FIRST 1
#define CALL_LAST 0
// this should be in <excpt.h>, but it's been removed from MinGW distributions
#ifndef EH_UNWINDING
#define EH_UNWINDING 0x02
#endif /* EH_UNWINDING */
// Registered exception handler
PVOID __hs_handle = NULL;
long WINAPI __hs_exception_handler(struct _EXCEPTION_POINTERS *exception_data)
{
long action = EXCEPTION_CONTINUE_SEARCH;
ULONG_PTR what;
// When the system unwinds the VEH stack after having handled an excn,
// return immediately.
if ((exception_data->ExceptionRecord->ExceptionFlags & EH_UNWINDING) == 0)
{
// Error handling cases covered by this implementation.
switch (exception_data->ExceptionRecord->ExceptionCode) {
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
fprintf(stdout, "divide by zero\n");
action = EXCEPTION_CONTINUE_EXECUTION;
break;
case EXCEPTION_STACK_OVERFLOW:
fprintf(stdout, "C stack overflow in generated code\n");
action = EXCEPTION_CONTINUE_EXECUTION;
break;
case EXCEPTION_ACCESS_VIOLATION:
what = exception_data->ExceptionRecord->ExceptionInformation[0];
fprintf(stdout, "Access violation in generated code"
" when %s %p\n"
, what == 0 ? "reading" : what == 1 ? "writing" : what == 8 ? "executing data at" : "?"
, (void*) exception_data->ExceptionRecord->ExceptionInformation[1]
);
action = EXCEPTION_CONTINUE_EXECUTION;
break;
default:;
}
// If an error has occurred and we've decided to continue execution
// then we've done so to prevent something else from handling the error.
// But the correct action is still to exit as fast as possible.
if (EXCEPTION_CONTINUE_EXECUTION == action)
{
fflush(stdout);
stg_exit(EXIT_FAILURE);
}
}
return action;
}
void __register_hs_exception_handler( void )
{
// Allow the VEH handler to be registered only once.
if (NULL == __hs_handle)
{
__hs_handle = AddVectoredExceptionHandler(CALL_FIRST, __hs_exception_handler);
// should the handler not be registered this will return a null.
assert(__hs_handle);
}
else
{
errorBelch("There is no need to call __register_hs_exception_handler() twice, VEH handlers are global per process.");
}
}
void __unregister_hs_exception_handler( void )
{
if (__hs_handle != NULL)
{
// Should the return value be checked? we're terminating anyway.
RemoveVectoredExceptionHandler(__hs_handle);
__hs_handle = NULL;
}
else
{
errorBelch("__unregister_hs_exception_handler() called without having called __register_hs_exception_handler() first.");
}
}
|