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
8namespace 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