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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
|
#ifndef CRASHHANDLER_H
#define CRASHHANDLER_H
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <new.h>
#include <signal.h>
#include <exception>
#include <sys/stat.h>
#include <psapi.h>
#include <rtcapi.h>
#include <Shellapi.h>
#include <dbghelp.h>
#include <functional>
#include <mutex>
#include <string>
#include <map>
#include "../common/common.h"
#ifdef __MINGW32__
typedef int (__cdecl *_CRT_REPORT_HOOK)(int,char *,int *);
#endif
namespace Debug {
struct ThreadExceptionHandlers
{
ThreadExceptionHandlers()
{
m_prevTerm = NULL;
m_prevUnexp = NULL;
m_prevSigFPE = NULL;
m_prevSigILL = NULL;
m_prevSigSEGV = NULL;
}
std::terminate_handler m_prevTerm; // Previous terminate handler
std::unexpected_handler m_prevUnexp; // Previous unexpected handler
void (__cdecl *m_prevSigFPE)(int); // Previous FPE handler
void (__cdecl *m_prevSigILL)(int); // Previous SIGILL handler
void (__cdecl *m_prevSigSEGV)(int); // Previous illegal storage access handler
};
// code mostly from https://www.codeproject.com/articles/207464/WebControls/
class WindowsCrashHandler
{
public:
static WindowsCrashHandler& getInstance()
{
static WindowsCrashHandler instance; // Guaranteed to be destroyed.
// Instantiated on first use.
return instance;
}
private:
WindowsCrashHandler();
public:
void setup(const std::wstring &appName, const std::wstring &dumpsDir);
void teardown();
void setCrashCallback(const std::function<void()> &callback);
void setBacktraceCallback(const std::function<void(const char * const)> &callback);
void handleCrash();
public:
bool isDataSectionNeeded(const WCHAR* pModuleName);
public:
// Sets exception handlers that work on per-process basis
void setProcessExceptionHandlers();
void unsetProcessExceptionHandlers();
// Installs C++ exception handlers that function on per-thread basis
int setThreadExceptionHandlers();
int unsetThreadExceptionHandlers();
/* Exception handler functions. */
static int __cdecl CrtReportHook(int nReportType, char* szMsg, int* pnRet);
static void __cdecl TerminateHandler();
static void __cdecl UnexpectedHandler();
static void __cdecl PureCallHandler();
#if _MSC_VER>=1300 && _MSC_VER<1400
// Buffer overrun handler (deprecated in newest versions of Visual C++).
// Since CRT 8.0, you can't intercept the buffer overrun errors in your code. When a buffer overrun is detected, CRT invokes Dr. Watson directly
static void __cdecl SecurityHandler(int code, void *x);
#endif
#if _MSC_VER>=1400
static void __cdecl InvalidParameterHandler(const wchar_t* expression,
const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved);
#endif
static int __cdecl NewHandler(size_t);
static void SigabrtHandler(int);
static void SigfpeHandler(int /*code*/, int subcode);
static void SigintHandler(int);
static void SigillHandler(int);
static void SigsegvHandler(int);
static void SigtermHandler(int);
static BOOL WINAPI ConsoleCtrlHandler(DWORD type);
private:
std::function<void()> m_crashCallback;
std::function<void(const char * const)> m_backtraceCallback;
std::mutex m_crashMutex;
std::wstring m_appName;
std::map<DWORD, ThreadExceptionHandlers> m_threadExceptionHandlers;
std::mutex m_threadHandlersMutex;
// Previous SEH exception filter.
LPTOP_LEVEL_EXCEPTION_FILTER m_oldSehHandler;
#if _MSC_VER>=1300
_purecall_handler m_prevPurec; // Previous pure virtual call exception filter.
_PNH m_prevNewHandler; // Previous new operator exception filter.
#endif
#if _MSC_VER>=1400
_invalid_parameter_handler m_prevInvpar; // Previous invalid parameter exception filter.
#endif
#if _MSC_VER>=1300 && _MSC_VER<1400
_secerr_handler_func m_prevSec; // Previous security exception filter.
#endif
void (__cdecl *m_prevSigABRT)(int); // Previous SIGABRT handler.
void (__cdecl *m_prevSigINT)(int); // Previous SIGINT handler.
void (__cdecl *m_prevSigTERM)(int); // Previous SIGTERM handler.
};
}
#endif
#endif // CRASHHANDLER_H
|