clientobject: add null checks
[waspsaliva.git] / src / debug.cpp
blob3c82ed9e1c23ec62e51fb5bc3e91d0c7608efa23
1 /*
2 Minetest
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.
21 #include "porting.h"
22 #include "debug.h"
23 #include "exceptions.h"
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <map>
28 #include <sstream>
29 #include <thread>
30 #include "threading/mutex_auto_lock.h"
31 #include "config.h"
33 #ifdef _MSC_VER
34 #include <dbghelp.h>
35 #include "version.h"
36 #include "filesys.h"
37 #endif
39 #if USE_CURSES
40 #include "terminal_chat_console.h"
41 #endif
44 Assert
47 void sanity_check_fn(const char *assertion, const char *file,
48 unsigned int line, const char *function)
50 #if USE_CURSES
51 g_term_console.stopAndWaitforThread();
52 #endif
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;
59 abort();
62 void fatal_error_fn(const char *msg, const char *file,
63 unsigned int line, const char *function)
65 #if USE_CURSES
66 g_term_console.stopAndWaitforThread();
67 #endif
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;
74 abort();
77 #ifdef _MSC_VER
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)
133 char buf[512];
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;
169 minidump_failed:
171 CloseHandle(hFile);
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);
179 dstream << buf;
181 if (minidump_created)
182 dstream << " >> Saved dump to " << dumpfile << std::endl;
183 else
184 dstream << " >> Failed to save dump" << std::endl;
186 return EXCEPTION_EXECUTE_HANDLER;
189 #endif
191 void debug_set_exception_handler()
193 #ifdef _MSC_VER
194 SetUnhandledExceptionFilter(Win32ExceptionHandler);
195 #endif