aboutsummaryrefslogtreecommitdiffstats
path: root/SQLiteStudio3/coreSQLiteStudio/chillout/windows/windowscrashhandler.h
blob: 9d7e70fe188e6afce5019434b5aa572549f372a8 (plain) (blame)
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