|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 #include <functional>
|
|
|
4
|
|
|
5 class uDebugLog_ : public pfc::string_formatter {
|
|
|
6 public:
|
|
|
7 ~uDebugLog_() {*this << "\n"; uOutputDebugString(get_ptr());}
|
|
|
8 };
|
|
|
9
|
|
|
10 #define FB2K_DebugLog() uDebugLog_()._formatter()
|
|
|
11 #define uDebugLog() FB2K_DebugLog()
|
|
|
12
|
|
|
13 // since fb2k 1.5
|
|
|
14 namespace fb2k {
|
|
|
15 class panicHandler {
|
|
|
16 public:
|
|
|
17 virtual void onPanic() = 0;
|
|
|
18 };
|
|
|
19 }
|
|
|
20
|
|
|
21 // since fb2k 1.5
|
|
|
22 extern "C"
|
|
|
23 {
|
|
|
24 void SHARED_EXPORT uAddPanicHandler(fb2k::panicHandler*);
|
|
|
25 void SHARED_EXPORT uRemovePanicHandler(fb2k::panicHandler*);
|
|
|
26 }
|
|
|
27
|
|
|
28 extern "C"
|
|
|
29 {
|
|
|
30 #ifdef _WIN32
|
|
|
31 LPCSTR SHARED_EXPORT uGetCallStackPath();
|
|
|
32 LONG SHARED_EXPORT uExceptFilterProc(LPEXCEPTION_POINTERS param);
|
|
|
33 #endif
|
|
|
34
|
|
|
35 PFC_NORETURN void SHARED_EXPORT uBugCheck();
|
|
|
36
|
|
|
37 #if PFC_DEBUG
|
|
|
38 void SHARED_EXPORT fb2kDebugSelfTest();
|
|
|
39 #endif
|
|
|
40
|
|
|
41 #ifdef _WIN32
|
|
|
42 static inline void uAddDebugEvent(const char * msg) {uPrintCrashInfo_OnEvent(msg, SIZE_MAX);}
|
|
|
43 #else
|
|
|
44 static inline void uAddDebugEvent( const char * msg ) { uOutputDebugString(pfc::format(msg, "\n")); }
|
|
|
45 #endif
|
|
|
46 }
|
|
|
47
|
|
|
48 #ifdef _WIN32
|
|
|
49 class uCallStackTracker {
|
|
|
50 t_size param;
|
|
|
51 public:
|
|
|
52 explicit SHARED_EXPORT uCallStackTracker(const char* name);
|
|
|
53 SHARED_EXPORT ~uCallStackTracker();
|
|
|
54 };
|
|
|
55 #endif
|
|
|
56
|
|
|
57 #if FB2K_SUPPORT_CRASH_LOGS
|
|
|
58
|
|
|
59 #define TRACK_CALL(X) uCallStackTracker TRACKER__##X(#X)
|
|
|
60 #define TRACK_CALL_TEXT(X) uCallStackTracker TRACKER__BLAH(X)
|
|
|
61 #define TRACK_CODE(description,code) {uCallStackTracker __call_tracker(description); code;}
|
|
|
62
|
|
|
63 #else // FB2K_SUPPORT_CRASH_LOGS
|
|
|
64
|
|
|
65 #define TRACK_CALL(X)
|
|
|
66 #define TRACK_CALL_TEXT(X)
|
|
|
67 #define TRACK_CODE(description,code) {code;}
|
|
|
68
|
|
|
69 #endif // FB2K_SUPPORT_CRASH_LOGS
|
|
|
70
|
|
|
71 #if FB2K_SUPPORT_CRASH_LOGS
|
|
|
72 inline int uExceptFilterProc_inline(LPEXCEPTION_POINTERS param) {
|
|
|
73 uDumpCrashInfo(param);
|
|
|
74 TerminateProcess(GetCurrentProcess(), 0);
|
|
|
75 return 0;// never reached
|
|
|
76 }
|
|
|
77 #endif
|
|
|
78
|
|
|
79
|
|
|
80 #define FB2K_DYNAMIC_ASSERT( X ) { if (!(X)) uBugCheck(); }
|
|
|
81
|
|
|
82 #if FB2K_SUPPORT_CRASH_LOGS
|
|
|
83 #define __except_instacrash __except(uExceptFilterProc(GetExceptionInformation()))
|
|
|
84 #define fb2k_instacrash_scope(X) __try { X; } __except_instacrash {}
|
|
|
85 #else
|
|
|
86 #define fb2k_instacrash_scope(X) {X;}
|
|
|
87 #endif
|
|
|
88
|
|
|
89 #if 0 // no longer used
|
|
|
90 PFC_NORETURN inline void fb2kCriticalError(DWORD code, DWORD argCount = 0, const ULONG_PTR * args = NULL) {
|
|
|
91 fb2k_instacrash_scope( RaiseException(code,EXCEPTION_NONCONTINUABLE,argCount,args); );
|
|
|
92 }
|
|
|
93 PFC_NORETURN inline void fb2kDeadlock() {
|
|
|
94 fb2kCriticalError(0x63d81b66);
|
|
|
95 }
|
|
|
96 #endif
|
|
|
97
|
|
|
98 #ifdef _WIN32
|
|
|
99 inline void fb2kWaitForCompletion(HANDLE hEvent) {
|
|
|
100 switch(WaitForSingleObject(hEvent, INFINITE)) {
|
|
|
101 case WAIT_OBJECT_0:
|
|
|
102 return;
|
|
|
103 default:
|
|
|
104 uBugCheck();
|
|
|
105 }
|
|
|
106 }
|
|
|
107
|
|
|
108 inline void fb2kWaitForThreadCompletion(HANDLE hWaitFor, DWORD threadID) {
|
|
|
109 (void) threadID;
|
|
|
110 switch(WaitForSingleObject(hWaitFor, INFINITE)) {
|
|
|
111 case WAIT_OBJECT_0:
|
|
|
112 return;
|
|
|
113 default:
|
|
|
114 uBugCheck();
|
|
|
115 }
|
|
|
116 }
|
|
|
117
|
|
|
118 inline void fb2kWaitForThreadCompletion2(HANDLE hWaitFor, HANDLE hThread, DWORD threadID) {
|
|
|
119 (void)threadID; (void)hThread;
|
|
|
120 switch(WaitForSingleObject(hWaitFor, INFINITE)) {
|
|
|
121 case WAIT_OBJECT_0:
|
|
|
122 return;
|
|
|
123 default:
|
|
|
124 uBugCheck();
|
|
|
125 }
|
|
|
126 }
|
|
|
127
|
|
|
128
|
|
|
129 inline void __cdecl _OverrideCrtAbort_handler(int signal) {
|
|
|
130 const ULONG_PTR args[] = {(ULONG_PTR)signal};
|
|
|
131 RaiseException(0x6F8E1DC8 /* random GUID */, EXCEPTION_NONCONTINUABLE, _countof(args), args);
|
|
|
132 }
|
|
|
133
|
|
|
134 static void __cdecl _PureCallHandler() {
|
|
|
135 RaiseException(0xf6538887 /* random GUID */, EXCEPTION_NONCONTINUABLE, 0, 0);
|
|
|
136 }
|
|
|
137
|
|
|
138 static void _InvalidParameter(
|
|
|
139 const wchar_t * expression,
|
|
|
140 const wchar_t * function,
|
|
|
141 const wchar_t * file,
|
|
|
142 unsigned int line,
|
|
|
143 uintptr_t pReserved
|
|
|
144 ) {
|
|
|
145 (void)pReserved; (void) line; (void) file; (void) function; (void) expression;
|
|
|
146 RaiseException(0xd142b808 /* random GUID */, EXCEPTION_NONCONTINUABLE, 0, 0);
|
|
|
147 }
|
|
|
148
|
|
|
149 inline void OverrideCrtAbort() {
|
|
|
150 const int signals[] = {SIGINT, SIGTERM, SIGBREAK, SIGABRT};
|
|
|
151 for(size_t i=0; i<_countof(signals); i++) signal(signals[i], _OverrideCrtAbort_handler);
|
|
|
152 _set_abort_behavior(0, UINT_MAX);
|
|
|
153
|
|
|
154 _set_purecall_handler(_PureCallHandler);
|
|
|
155 _set_invalid_parameter_handler(_InvalidParameter);
|
|
|
156 }
|
|
|
157 #endif
|
|
|
158
|
|
|
159 namespace fb2k {
|
|
|
160 #ifdef _WIN32
|
|
|
161 PFC_NORETURN inline void crashWithMessage(const char * msg) {
|
|
|
162 uAddDebugEvent(msg);
|
|
|
163 uBugCheck();
|
|
|
164 }
|
|
|
165 inline void crashOnException(std::function<void()> const & f, const char* context = nullptr) {
|
|
|
166 (void)context;
|
|
|
167 fb2k_instacrash_scope(f());
|
|
|
168 }
|
|
|
169 #else
|
|
|
170 void crashWithMessage [[noreturn]] (const char*);
|
|
|
171 void crashOnException(std::function<void()>, const char* context = nullptr);
|
|
|
172 #endif
|
|
|
173
|
|
|
174 }
|
|
|
175
|
|
|
176 #define FB2K_CrashOnException( ... ) ::fb2k::crashWithMessage(__VA_ARGS__)
|
|
|
177
|
|
|
178
|
|
|
179 // implement me
|
|
|
180 #define FB2K_TRACE_ENABLED 0
|
|
|
181
|
|
|
182 #define FB2K_TRACE_FORCED(X)
|
|
|
183 #define FB2K_TRACE(X)
|
|
|
184 #define FB2K_TRACE_THIS FB2K_TRACE(__FUNCTION__)
|
|
|
185 #define FB2K_TRACE_THIS_FORCED FB2K_TRACE_FORCED(__FUNCTION__)
|
|
|
186
|
|
|
187 #define FB2K_BugCheck() fb2k::crashWithMessage( pfc::format("FB2K_BugCheck: ", __FUNCTION__ ) )
|
|
|
188 #define FB2K_BugCheckEx(msg) fb2k::crashWithMessage(msg)
|
|
|
189 #define FB2K_BugCheckUnlikely() uBugCheck()
|