3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "exceptions.h"
30 #include "threading/mutex_auto_lock.h"
40 #include "terminal_chat_console.h"
47 void sanity_check_fn(const char *assertion
, const char *file
,
48 unsigned int line
, const char *function
)
51 g_term_console
.stopAndWaitforThread();
54 errorstream
<< std::endl
<< "In thread " << std::hex
55 << std::this_thread::get_id() << ":" << std::endl
;
56 errorstream
<< file
<< ":" << line
<< ": " << function
57 << ": An engine assumption '" << assertion
<< "' failed." << std::endl
;
62 void fatal_error_fn(const char *msg
, const char *file
,
63 unsigned int line
, const char *function
)
66 g_term_console
.stopAndWaitforThread();
69 errorstream
<< std::endl
<< "In thread " << std::hex
70 << std::this_thread::get_id() << ":" << std::endl
;
71 errorstream
<< file
<< ":" << line
<< ": " << function
72 << ": A fatal error occurred: " << msg
<< std::endl
;
79 const char *Win32ExceptionCodeToString(DWORD exception_code
)
81 switch (exception_code
) {
82 case EXCEPTION_ACCESS_VIOLATION
:
83 return "Access violation";
84 case EXCEPTION_DATATYPE_MISALIGNMENT
:
85 return "Misaligned data access";
86 case EXCEPTION_BREAKPOINT
:
87 return "Breakpoint reached";
88 case EXCEPTION_SINGLE_STEP
:
89 return "Single debug step";
90 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED
:
91 return "Array access out of bounds";
92 case EXCEPTION_FLT_DENORMAL_OPERAND
:
93 return "Denormal floating point operand";
94 case EXCEPTION_FLT_DIVIDE_BY_ZERO
:
95 return "Floating point division by zero";
96 case EXCEPTION_FLT_INEXACT_RESULT
:
97 return "Inaccurate floating point result";
98 case EXCEPTION_FLT_INVALID_OPERATION
:
99 return "Invalid floating point operation";
100 case EXCEPTION_FLT_OVERFLOW
:
101 return "Floating point exponent overflow";
102 case EXCEPTION_FLT_STACK_CHECK
:
103 return "Floating point stack overflow or underflow";
104 case EXCEPTION_FLT_UNDERFLOW
:
105 return "Floating point exponent underflow";
106 case EXCEPTION_INT_DIVIDE_BY_ZERO
:
107 return "Integer division by zero";
108 case EXCEPTION_INT_OVERFLOW
:
109 return "Integer overflow";
110 case EXCEPTION_PRIV_INSTRUCTION
:
111 return "Privileged instruction executed";
112 case EXCEPTION_IN_PAGE_ERROR
:
113 return "Could not access or load page";
114 case EXCEPTION_ILLEGAL_INSTRUCTION
:
115 return "Illegal instruction encountered";
116 case EXCEPTION_NONCONTINUABLE_EXCEPTION
:
117 return "Attempted to continue after fatal exception";
118 case EXCEPTION_STACK_OVERFLOW
:
119 return "Stack overflow";
120 case EXCEPTION_INVALID_DISPOSITION
:
121 return "Invalid disposition returned to the exception dispatcher";
122 case EXCEPTION_GUARD_PAGE
:
123 return "Attempted guard page access";
124 case EXCEPTION_INVALID_HANDLE
:
125 return "Invalid handle";
128 return "Unknown exception";
131 long WINAPI
Win32ExceptionHandler(struct _EXCEPTION_POINTERS
*pExceptInfo
)
134 MINIDUMP_EXCEPTION_INFORMATION mdei
;
135 MINIDUMP_USER_STREAM_INFORMATION mdusi
;
136 MINIDUMP_USER_STREAM mdus
;
137 bool minidump_created
= false;
139 std::string dumpfile
= porting::path_user
+ DIR_DELIM PROJECT_NAME
".dmp";
141 std::string
version_str(PROJECT_NAME
" ");
142 version_str
+= g_version_hash
;
144 HANDLE hFile
= CreateFileA(dumpfile
.c_str(), GENERIC_WRITE
,
145 FILE_SHARE_WRITE
, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
146 if (hFile
== INVALID_HANDLE_VALUE
)
147 goto minidump_failed
;
149 if (SetEndOfFile(hFile
) == FALSE
)
150 goto minidump_failed
;
152 mdei
.ClientPointers
= NULL
;
153 mdei
.ExceptionPointers
= pExceptInfo
;
154 mdei
.ThreadId
= GetCurrentThreadId();
156 mdus
.Type
= CommentStreamA
;
157 mdus
.BufferSize
= version_str
.size();
158 mdus
.Buffer
= (PVOID
)version_str
.c_str();
160 mdusi
.UserStreamArray
= &mdus
;
161 mdusi
.UserStreamCount
= 1;
163 if (MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hFile
,
164 MiniDumpNormal
, &mdei
, &mdusi
, NULL
) == FALSE
)
165 goto minidump_failed
;
167 minidump_created
= true;
173 DWORD excode
= pExceptInfo
->ExceptionRecord
->ExceptionCode
;
174 _snprintf(buf
, sizeof(buf
),
175 " >> === FATAL ERROR ===\n"
176 " >> %s (Exception 0x%08X) at 0x%p\n",
177 Win32ExceptionCodeToString(excode
), excode
,
178 pExceptInfo
->ExceptionRecord
->ExceptionAddress
);
181 if (minidump_created
)
182 dstream
<< " >> Saved dump to " << dumpfile
<< std::endl
;
184 dstream
<< " >> Failed to save dump" << std::endl
;
186 return EXCEPTION_EXECUTE_HANDLER
;
191 void debug_set_exception_handler()
194 SetUnhandledExceptionFilter(Win32ExceptionHandler
);