1 | //************************************ bs::framework - Copyright 2018 Marko Pintera **************************************// |
2 | //*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********// |
3 | #pragma once |
4 | |
5 | #define BS_MAX_STACKTRACE_DEPTH 200 |
6 | #define BS_MAX_STACKTRACE_NAME_BYTES 1024 |
7 | |
8 | namespace bs |
9 | { |
10 | /** @addtogroup Internal-Utility |
11 | * @{ |
12 | */ |
13 | |
14 | /** @addtogroup Error-Internal |
15 | * @{ |
16 | */ |
17 | |
18 | /** Saves crash data and notifies the user when a crash occurs. */ |
19 | // TODO - Crashes are reported in the same process as the main application. This can be a problem if the crash was caused |
20 | // by heap. Any further use of the heap by the reporting methods will cause a silent crash, failing to log it. A more |
21 | // appropriate way of doing it should be to resume another process to actually handle the crash. |
22 | // - Perhaps an even better option would be to use a private heap for all engine allocations. So when corruptions does |
23 | // happen the crash handler can use the default heap with no issues. |
24 | class BS_UTILITY_EXPORT CrashHandler |
25 | { |
26 | public: |
27 | CrashHandler(); |
28 | ~CrashHandler(); |
29 | |
30 | /** Constructs and starts the module. */ |
31 | static void startUp() |
32 | { |
33 | if(_instance() == nullptr) |
34 | _instance() = bs_new<CrashHandler>(); |
35 | } |
36 | |
37 | /** Shuts down this module and frees any resources it is using. */ |
38 | static void shutDown() |
39 | { |
40 | if(_instance() != nullptr) |
41 | { |
42 | bs_delete(_instance()); |
43 | _instance() = nullptr; |
44 | } |
45 | } |
46 | |
47 | /** Returns a reference to the module instance. */ |
48 | static CrashHandler& instance() { return *_instance(); } |
49 | |
50 | /** |
51 | * Records a crash with a custom error message. |
52 | * |
53 | * @param[in] type Type of the crash that occurred. For example "InvalidParameter". |
54 | * @param[in] description More detailed description of the issue that caused the crash. |
55 | * @param[in] function Optional name of the function where the error occurred. |
56 | * @param[in] file Optional name of the source code file in which the code that crashed the program exists. |
57 | * @param[in] line Optional source code line at which the crash was triggered at. |
58 | */ |
59 | void reportCrash(const String& type, const String& description, const String& function = StringUtil::BLANK, |
60 | const String& file = StringUtil::BLANK, UINT32 line = 0) const; |
61 | |
62 | #if BS_PLATFORM == BS_PLATFORM_WIN32 |
63 | /** |
64 | * Records a crash resulting from a Windows-specific SEH exception. |
65 | * |
66 | * @param[in] exceptionData Exception data returned from GetExceptionInformation() |
67 | * @return Code that signals the __except exception handler on how to proceed. |
68 | * |
69 | * @note Available in Windows builds only. |
70 | */ |
71 | int reportCrash(void* exceptionData) const; |
72 | #endif |
73 | |
74 | /** |
75 | * Returns a string containing a current stack trace. If function can be found in the symbol table its readable |
76 | * name will be present in the stack trace, otherwise just its address. |
77 | * |
78 | * @return String containing the call stack with each function on its own line. |
79 | */ |
80 | static String getStackTrace(); |
81 | private: |
82 | /** Does what it says. Internal utility function used by reportCrash(). */ |
83 | void logErrorAndStackTrace(const String& message, const String& stackTrace) const; |
84 | /** Does what it says. Internal utility function used by reportCrash(). */ |
85 | void logErrorAndStackTrace(const String& type, |
86 | const String& description, |
87 | const String& function, |
88 | const String& file, |
89 | UINT32 line) const; |
90 | /** Does what it says. Internal utility function used by reportCrash(). */ |
91 | void saveCrashLog() const; |
92 | /** Creates the crash report directory and returns its path. */ |
93 | static const Path& getCrashFolder(); |
94 | /** Returns the current time as a string timestamp. This is used |
95 | * to name the crash report directory.. */ |
96 | static String getCrashTimestamp(); |
97 | |
98 | /** Returns a singleton instance of this module. */ |
99 | static CrashHandler*& _instance() { static CrashHandler* inst = nullptr; return inst; } |
100 | |
101 | /** The name of the crash reports directory. */ |
102 | static const String sCrashReportFolder; |
103 | /** The name of the HTML crash log file. */ |
104 | static const String sCrashLogName; |
105 | /** Error message to display on program failure. */ |
106 | static const String sFatalErrorMsg; |
107 | |
108 | #if BS_PLATFORM == BS_PLATFORM_WIN32 |
109 | struct Data; |
110 | Data* m; |
111 | #endif |
112 | }; |
113 | |
114 | /** Easier way of accessing the CrashHandler. */ |
115 | BS_UTILITY_EXPORT CrashHandler& gCrashHandler(); |
116 | |
117 | /** @} */ |
118 | /** @} */ |
119 | } |
120 | |