CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
exceptions_handler.cpp
Go to the documentation of this file.
1
10
11#include "filesystem/path.h"
12#include "system/stack_trace.h"
13#include "time/timestamp.h"
14#include "utility/resource.h"
16
17#include <cstring>
18#include <exception>
19#include <iostream>
20
21#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
22#include "string/format.h"
23#include "utility/countof.h"
24#include <signal.h>
25#include <unistd.h>
26#elif defined(_WIN32) || defined(_WIN64)
27#if defined(_MSC_VER)
28#include <intrin.h>
29#endif
30#include <csignal>
31#include <new.h>
32#include <windows.h>
33#if defined(DBGHELP_SUPPORT)
34#include "string/format.h"
35#if defined(_MSC_VER)
36#pragma warning(push)
37#pragma warning(disable:4091) // C4091: 'keyword' : ignored on left of 'type' when no variable is declared
38#endif
39#include <dbghelp.h>
40#if defined(_MSC_VER)
41#pragma warning(pop)
42#endif
43#endif
44#endif
45
46namespace CppCommon {
47
49
50class ExceptionsHandler::Impl
51{
52public:
53 Impl() : _initialized(false), _handler(ExceptionsHandler::Impl::DefaultHandler) {}
54
55 static ExceptionsHandler::Impl& GetInstance()
56 { return ExceptionsHandler::GetInstance().impl(); }
57
58 void SetupHandler(const std::function<void (const SystemException&, const StackTrace&)>& handler)
59 {
60 assert((handler) && "Exceptions handler function must be valid!");
61 if (!handler)
62 return;
63
64 _handler = handler;
65 }
66
67 void SetupProcess()
68 {
69 // Check for double initialization
70 if (_initialized)
71 return;
72
73#if defined(_WIN32) || defined(_WIN64)
74 // Install top-level SEH handler
75 SetUnhandledExceptionFilter(SehHandler);
76
77#if defined(_MSC_VER)
78 // Catch pure virtual function calls
79 // Because there is one _purecall_handler for the whole process,
80 // calling this function immediately impacts all threads. The last
81 // caller on any thread sets the handler.
82 // http://msdn.microsoft.com/en-us/library/t296ys27.aspx
83 _set_purecall_handler(PureCallHandler);
84
85 // Catch new operator memory allocation exceptions
86 _set_new_handler(NewHandler);
87
88 // Catch invalid parameter exceptions
89 _set_invalid_parameter_handler(InvalidParameterHandler);
90
91 // Set up C++ signal handlers
92 _set_abort_behavior(_CALL_REPORTFAULT, _CALL_REPORTFAULT);
93#endif
94
95 // Catch an abnormal program termination
96 signal(SIGABRT, SigabrtHandler);
97
98 // Catch an illegal instruction error
99 signal(SIGINT, SigintHandler);
100
101 // Catch a termination request
102 signal(SIGTERM, SigtermHandler);
103#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
104 // Prepare signal action structure
105 struct sigaction sa;
106 memset(&sa, 0, sizeof(sa));
107 sa.sa_sigaction = SignalHandler;
108 sa.sa_flags = SA_SIGINFO;
109
110 // Define signals to catch
111 int signals[] =
112 {
113 SIGABRT,
114 SIGALRM,
115 SIGBUS,
116 SIGFPE,
117 SIGHUP,
118 SIGILL,
119 SIGINT,
120 SIGPIPE,
121 SIGPROF,
122 SIGQUIT,
123 SIGSEGV,
124 SIGSYS,
125 SIGTERM,
126 SIGXCPU,
127 SIGXFSZ
128 };
129
130 // Setup corresponding signals handlers
131 for (size_t i = 0; i < countof(signals); ++i)
132 {
133 int result = sigaction(signals[i], &sa, nullptr);
134 if (result != 0)
135 throwex SystemException(format("Failed to setup signal handler - {}", signals[i]));
136 }
137#endif
138
139 _initialized = true;
140 }
141
142 static void SetupThread()
143 {
144#if defined(_WIN32) || defined(_WIN64)
145#if defined(_MSC_VER)
146 // Catch std::terminate() calls
147 // In a multithreaded environment, terminate functions are maintained
148 // separately for each thread. Each new thread needs to install its own
149 // terminate function. Thus, each thread is in charge of its own termination handling.
150 // http://msdn.microsoft.com/en-us/library/t6fk7h29.aspx
151 std::set_terminate(TerminateHandler);
152
153#if (__cplusplus < 201703L)
154 // Catch std::unexpected() calls
155 // In a multithreaded environment, unexpected functions are maintained
156 // separately for each thread. Each new thread needs to install its own
157 // unexpected function. Thus, each thread is in charge of its own unexpected handling.
158 // http://msdn.microsoft.com/en-us/library/h46t5b69.aspx
159 std::set_unexpected(UnexpectedHandler);
160#endif
161#endif
162
163 // Catch a floating point exception
164 typedef void (*sigh)(int);
165 signal(SIGFPE, (sigh)SigfpeHandler);
166
167 // Catch an illegal instruction
168 signal(SIGILL, SigillHandler);
169
170 // Catch an illegal storage access error
171 signal(SIGSEGV, SigsegvHandler);
172#endif
173 }
174
175private:
176 // Initialization flag for the current process
177 bool _initialized;
178 // Exception handler function
179 std::function<void (const SystemException&, const StackTrace&)> _handler;
180
181 // Default exception handler function
182 static void DefaultHandler(const SystemException& exception, const StackTrace& trace)
183 {
184 std::cerr << exception;
185 std::cerr << "Stack trace:" << std::endl;
186 std::cerr << trace;
187 }
188
189#if defined(_WIN32) || defined(_WIN64)
190
191 // Structured exception handler
192 static LONG WINAPI SehHandler(PEXCEPTION_POINTERS pExceptionPtrs)
193 {
194 // Output error
195 GetInstance()._handler(__LOCATION__ + SystemException("Unhandled SEH exception"), StackTrace(1));
196
197 // Write dump file
198 CreateDumpFile(pExceptionPtrs);
199
200 // Terminate process
201 TerminateProcess(GetCurrentProcess(), 1);
202
203 // Unreacheable code
204 return EXCEPTION_EXECUTE_HANDLER;
205 }
206
207#if defined(_MSC_VER)
208 // CRT terminate() call handler
209 static void __cdecl TerminateHandler()
210 {
211 // Output error
212 GetInstance()._handler(__LOCATION__ + SystemException("Abnormal program termination (terminate() function was called)"), StackTrace(1));
213
214 // Retrieve exception information
215 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
216 GetExceptionPointers(0, &pExceptionPtrs);
217
218 // Write dump file
219 CreateDumpFile(pExceptionPtrs);
220
221 // Delete exception information
222 DeleteExceptionPointers(pExceptionPtrs);
223
224 // Terminate process
225 TerminateProcess(GetCurrentProcess(), 1);
226 }
227
228 // CRT unexpected() call handler
229 static void __cdecl UnexpectedHandler()
230 {
231 // Output error
232 GetInstance()._handler(__LOCATION__ + SystemException("Unexpected error (unexpected() function was called)"), StackTrace(1));
233
234 // Retrieve exception information
235 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
236 GetExceptionPointers(0, &pExceptionPtrs);
237
238 // Write dump file
239 CreateDumpFile(pExceptionPtrs);
240
241 // Delete exception information
242 DeleteExceptionPointers(pExceptionPtrs);
243
244 // Terminate process
245 TerminateProcess(GetCurrentProcess(), 1);
246 }
247#endif
248
249 // CRT Pure virtual method call handler
250 static void __cdecl PureCallHandler()
251 {
252 // Output error
253 GetInstance()._handler(__LOCATION__ + SystemException("Pure virtual function call"), StackTrace(1));
254
255 // Retrieve exception information
256 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
257 GetExceptionPointers(0, &pExceptionPtrs);
258
259 // Write dump file
260 CreateDumpFile(pExceptionPtrs);
261
262 // Delete exception information
263 DeleteExceptionPointers(pExceptionPtrs);
264
265 // Terminate process
266 TerminateProcess(GetCurrentProcess(), 1);
267 }
268
269 // CRT invalid parameter handler
270 static void __cdecl InvalidParameterHandler(const wchar_t* expression, const wchar_t* function, const wchar_t* file, unsigned int line, uintptr_t pReserved)
271 {
272 // Output error
273 GetInstance()._handler(__LOCATION__ + SystemException("Invalid parameter exception"), StackTrace(1));
274
275 // Retrieve exception information
276 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
277 GetExceptionPointers(0, &pExceptionPtrs);
278
279 // Write dump file
280 CreateDumpFile(pExceptionPtrs);
281
282 // Delete exception information
283 DeleteExceptionPointers(pExceptionPtrs);
284
285 // Terminate process
286 TerminateProcess(GetCurrentProcess(), 1);
287 }
288
289 // CRT new operator fault handler
290 static int __cdecl NewHandler(size_t)
291 {
292 // Output error
293 GetInstance()._handler(__LOCATION__ + SystemException("'new' operator memory allocation exception"), StackTrace(1));
294
295 // Retrieve exception information
296 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
297 GetExceptionPointers(0, &pExceptionPtrs);
298
299 // Write dump file
300 CreateDumpFile(pExceptionPtrs);
301
302 // Delete exception information
303 DeleteExceptionPointers(pExceptionPtrs);
304
305 // Terminate process
306 TerminateProcess(GetCurrentProcess(), 1);
307
308 // Unreacheable code
309 return 0;
310 }
311
312 // CRT SIGABRT signal handler
313 static void SigabrtHandler(int signum)
314 {
315 // Output error
316 GetInstance()._handler(__LOCATION__ + SystemException("Caught abort (SIGABRT) signal"), StackTrace(1));
317
318 // Retrieve exception information
319 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
320 GetExceptionPointers(0, &pExceptionPtrs);
321
322 // Write dump file
323 CreateDumpFile(pExceptionPtrs);
324
325 // Delete exception information
326 DeleteExceptionPointers(pExceptionPtrs);
327
328 // Terminate process
329 TerminateProcess(GetCurrentProcess(), 1);
330 }
331
332 // CRT SIGFPE signal handler
333 static void SigfpeHandler(int signum, int subcode)
334 {
335 // Output error
336 GetInstance()._handler(__LOCATION__ + SystemException("Caught floating point exception (SIGFPE) signal"), StackTrace(1));
337
338 // Retrieve exception information
339 EXCEPTION_POINTERS* pExceptionPtrs = (PEXCEPTION_POINTERS)_pxcptinfoptrs;
340
341 // Write dump file
342 CreateDumpFile(pExceptionPtrs);
343
344 // Terminate process
345 TerminateProcess(GetCurrentProcess(), 1);
346 }
347
348 // CRT sigill signal handler
349 static void SigillHandler(int signum)
350 {
351 // Output error
352 GetInstance()._handler(__LOCATION__ + SystemException("Caught illegal instruction (SIGILL) signal"), StackTrace(1));
353
354 // Retrieve exception information
355 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
356 GetExceptionPointers(0, &pExceptionPtrs);
357
358 // Write dump file
359 CreateDumpFile(pExceptionPtrs);
360
361 // Delete exception information
362 DeleteExceptionPointers(pExceptionPtrs);
363
364 // Terminate process
365 TerminateProcess(GetCurrentProcess(), 1);
366 }
367
368 // CRT sigint signal handler
369 static void SigintHandler(int signum)
370 {
371 // Output error
372 GetInstance()._handler(__LOCATION__ + SystemException("Caught interruption (SIGINT) signal"), StackTrace(1));
373
374 // Retrieve exception information
375 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
376 GetExceptionPointers(0, &pExceptionPtrs);
377
378 // Write dump file
379 CreateDumpFile(pExceptionPtrs);
380
381 // Delete exception information
382 DeleteExceptionPointers(pExceptionPtrs);
383
384 // Terminate process
385 TerminateProcess(GetCurrentProcess(), 1);
386 }
387
388 // CRT SIGSEGV signal handler
389 static void SigsegvHandler(int signum)
390 {
391 // Output error
392 GetInstance()._handler(__LOCATION__ + SystemException("Caught invalid storage access (SIGSEGV) signal"), StackTrace(1));
393
394 // Retrieve exception information
395 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
396 GetExceptionPointers(0, &pExceptionPtrs);
397
398 // Write dump file
399 CreateDumpFile(pExceptionPtrs);
400
401 // Terminate process
402 TerminateProcess(GetCurrentProcess(), 1);
403 }
404
405 // CRT SIGTERM signal handler
406 static void SigtermHandler(int signum)
407 {
408 // Output error
409 GetInstance()._handler(__LOCATION__ + SystemException("Caught termination request (SIGTERM) signal"), StackTrace(1));
410
411 // Retrieve exception information
412 EXCEPTION_POINTERS* pExceptionPtrs = nullptr;
413 GetExceptionPointers(0, &pExceptionPtrs);
414
415 // Write dump file
416 CreateDumpFile(pExceptionPtrs);
417
418 // Delete exception information
419 DeleteExceptionPointers(pExceptionPtrs);
420
421 // Terminate process
422 TerminateProcess(GetCurrentProcess(), 1);
423 }
424
425 static void GetExceptionPointers(DWORD dwExceptionCode, EXCEPTION_POINTERS** ppExceptionPointers)
426 {
427 CONTEXT ContextRecord;
428 memset(&ContextRecord, 0, sizeof(CONTEXT));
429
430 EXCEPTION_RECORD ExceptionRecord;
431 memset(&ExceptionRecord, 0, sizeof(EXCEPTION_RECORD));
432
433#if defined(_M_IX86)
434 // On x86, we reserve some extra stack which won't be used. That is to
435 // preserve as much of the call frame as possible when the function with
436 // the buffer overrun entered __security_check_cookie with a JMP instead
437 // of a CALL, after the calling frame has been released in the epilogue
438 // of that function.
439 volatile ULONG dw[(sizeof(CONTEXT) + sizeof(EXCEPTION_RECORD)) / sizeof(ULONG)];
440
441 // Save the state in the context record immediately. Hopefully, since
442 // opts are disabled, this will happen without modifying ECX, which has
443 // the local cookie which failed the check.
444 __asm
445 {
446 mov dword ptr [ContextRecord.Eax ], eax
447 mov dword ptr [ContextRecord.Ecx ], ecx
448 mov dword ptr [ContextRecord.Edx ], edx
449 mov dword ptr [ContextRecord.Ebx ], ebx
450 mov dword ptr [ContextRecord.Esi ], esi
451 mov dword ptr [ContextRecord.Edi ], edi
452 mov word ptr [ContextRecord.SegSs], ss
453 mov word ptr [ContextRecord.SegCs], cs
454 mov word ptr [ContextRecord.SegDs], ds
455 mov word ptr [ContextRecord.SegEs], es
456 mov word ptr [ContextRecord.SegFs], fs
457 mov word ptr [ContextRecord.SegGs], gs
458 pushfd
459 pop [ContextRecord.EFlags]
460
461 // Set the context EBP/EIP/ESP to the values which would be found
462 // in the caller to __security_check_cookie.
463 mov eax, [ebp]
464 mov dword ptr [ContextRecord.Ebp], eax
465 mov eax, [ebp + 4]
466 mov dword ptr [ContextRecord.Eip], eax
467 lea eax, [ebp + 8]
468 mov dword ptr [ContextRecord.Esp], eax
469
470 // Make sure the dummy stack space looks referenced.
471 mov eax, dword ptr dw
472 }
473
474 ContextRecord.ContextFlags = CONTEXT_CONTROL;
475 ExceptionRecord.ExceptionAddress = (PVOID)(ULONG_PTR)ContextRecord.Eip;
476#elif defined(_M_X64)
477 ULONG64 ControlPc;
478 ULONG64 EstablisherFrame;
479 ULONG64 ImageBase;
480 PRUNTIME_FUNCTION FunctionEntry;
481 PVOID HandlerData;
482
483 RtlCaptureContext(&ContextRecord);
484
485 ControlPc = ContextRecord.Rip;
486 FunctionEntry = RtlLookupFunctionEntry(ControlPc, &ImageBase, nullptr);
487
488 if (FunctionEntry != nullptr)
489 RtlVirtualUnwind(UNW_FLAG_NHANDLER, ImageBase, ControlPc, FunctionEntry, &ContextRecord, &HandlerData, &EstablisherFrame, nullptr);
490
491#if defined(__GNUC__)
492 void* return_address = __builtin_return_address(0);
493 ContextRecord.Rip = (ULONGLONG)return_address;
494 ContextRecord.Rsp = (ULONGLONG)__builtin_extract_return_addr(return_address) + 8;
495#elif defined(_MSC_VER)
496 ContextRecord.Rip = (ULONGLONG)_ReturnAddress();
497 ContextRecord.Rsp = (ULONGLONG)_AddressOfReturnAddress() + 8;
498#endif
499 ExceptionRecord.ExceptionAddress = (PVOID)ContextRecord.Rip;
500#else
501 #error Unsupported architecture
502#endif
503 ExceptionRecord.ExceptionCode = dwExceptionCode;
504#if defined(__GNUC__)
505 ExceptionRecord.ExceptionAddress = __builtin_return_address(0);
506#elif defined(_MSC_VER)
507 ExceptionRecord.ExceptionAddress = _ReturnAddress();
508#endif
509
510 CONTEXT* pContextRecord = new CONTEXT;
511 memcpy(pContextRecord, &ContextRecord, sizeof(CONTEXT));
512
513 EXCEPTION_RECORD* pExceptionRecord = new EXCEPTION_RECORD;
514 memcpy(pExceptionRecord, &ExceptionRecord, sizeof(EXCEPTION_RECORD));
515
516 *ppExceptionPointers = new EXCEPTION_POINTERS;
517 (*ppExceptionPointers)->ContextRecord = pContextRecord;
518 (*ppExceptionPointers)->ExceptionRecord = pExceptionRecord;
519 }
520
521 static void DeleteExceptionPointers(EXCEPTION_POINTERS* pExceptionPointers)
522 {
523 delete pExceptionPointers->ContextRecord;
524 delete pExceptionPointers->ExceptionRecord;
525 delete pExceptionPointers;
526 }
527
528 static void CreateDumpFile(EXCEPTION_POINTERS* pExcPtrs)
529 {
530#if defined(DBGHELP_SUPPORT)
531 // Generate dump file name based on the current timestamp
532 Path dump = Path::executable().parent() / format("crash.{}.dmp", Timestamp::utc());
533
534 // Create the dump file
535 HANDLE hDumpFile = CreateFileW(dump.wstring().c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
536 if (hDumpFile == INVALID_HANDLE_VALUE)
537 throwex FileSystemException("Cannot create a dump file!").Attach(dump);
538
539 // Smart resource cleaner pattern
540 auto file = resource(hDumpFile, [](HANDLE hObject) { CloseHandle(hObject); });
541
542 MINIDUMP_EXCEPTION_INFORMATION mei;
543 MINIDUMP_CALLBACK_INFORMATION mci;
544
545 // Prepare dump file information
546 mei.ThreadId = GetCurrentThreadId();
547 mei.ExceptionPointers = pExcPtrs;
548 mei.ClientPointers = FALSE;
549 mci.CallbackRoutine = nullptr;
550 mci.CallbackParam = nullptr;
551
552 // Write dump file information
553 if (!MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), file.get(), MiniDumpNormal, &mei, nullptr, &mci))
554 throwex FileSystemException("Cannot write a dump file!").Attach(dump);
555
556 // Release the resource manually
557 if (!CloseHandle(hDumpFile))
558 throwex FileSystemException("Cannot close a dump file!").Attach(dump);
559 file.release();
560#endif
561 }
562
563#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)
564
565 // Signal handler
566 static void SignalHandler(int signo, siginfo_t* info, void* context)
567 {
568 // Output error
569 switch (signo)
570 {
571 case SIGABRT:
572 GetInstance()._handler(__LOCATION__ + SystemException("Caught abnormal program termination (SIGABRT) signal"), StackTrace(1));
573 break;
574 case SIGALRM:
575 GetInstance()._handler(__LOCATION__ + SystemException("Caught alarm clock (SIGALRM) signal"), StackTrace(1));
576 break;
577 case SIGBUS:
578 GetInstance()._handler(__LOCATION__ + SystemException("Caught memory access error (SIGBUS) signal"), StackTrace(1));
579 break;
580 case SIGFPE:
581 GetInstance()._handler(__LOCATION__ + SystemException("Caught floating point exception (SIGFPE) signal"), StackTrace(1));
582 break;
583 case SIGHUP:
584 GetInstance()._handler(__LOCATION__ + SystemException("Caught hangup instruction (SIGHUP) signal"), StackTrace(1));
585 break;
586 case SIGILL:
587 GetInstance()._handler(__LOCATION__ + SystemException("Caught illegal instruction (SIGILL) signal"), StackTrace(1));
588 break;
589 case SIGINT:
590 GetInstance()._handler(__LOCATION__ + SystemException("Caught terminal interrupt (SIGINT) signal"), StackTrace(1));
591 break;
592 case SIGPIPE:
593 GetInstance()._handler(__LOCATION__ + SystemException("Caught pipe write error (SIGPIPE) signal"), StackTrace(1));
594 break;
595 case SIGPROF:
596 GetInstance()._handler(__LOCATION__ + SystemException("Caught profiling timer expired error (SIGPROF) signal"), StackTrace(1));
597 break;
598 case SIGQUIT:
599 GetInstance()._handler(__LOCATION__ + SystemException("Caught terminal quit (SIGQUIT) signal"), StackTrace(1));
600 break;
601 case SIGSEGV:
602 GetInstance()._handler(__LOCATION__ + SystemException("Caught illegal storage access error (SIGSEGV) signal"), StackTrace(1));
603 break;
604 case SIGSYS:
605 GetInstance()._handler(__LOCATION__ + SystemException("Caught bad system call (SIGSYS) signal"), StackTrace(1));
606 break;
607 case SIGTERM:
608 GetInstance()._handler(__LOCATION__ + SystemException("Caught termination request (SIGTERM) signal"), StackTrace(1));
609 break;
610 case SIGXCPU:
611 GetInstance()._handler(__LOCATION__ + SystemException("Caught CPU time limit exceeded (SIGXCPU) signal"), StackTrace(1));
612 break;
613 case SIGXFSZ:
614 GetInstance()._handler(__LOCATION__ + SystemException("Caught file size limit exceeded (SIGXFSZ) signal"), StackTrace(1));
615 break;
616 default:
617 GetInstance()._handler(__LOCATION__ + SystemException(format("Caught unknown signal - {}", signo)), StackTrace(1));
618 break;
619 }
620
621 // Prepare signal action structure
622 struct sigaction sa;
623 memset(&sa, 0, sizeof(sa));
624 sa.sa_handler = SIG_DFL;
625
626 // Setup the default signal handler and rise it!
627 int result = sigaction(signo, &sa, nullptr);
628 if (result == 0)
629 raise(signo);
630 else
631 kill(getpid(), SIGKILL);
632 }
633
634#endif
635};
636
638
639ExceptionsHandler::ExceptionsHandler()
640{
641 // Check implementation storage parameters
642 [[maybe_unused]] ValidateAlignedStorage<sizeof(Impl), alignof(Impl), StorageSize, StorageAlign> _;
643 static_assert((StorageSize >= sizeof(Impl)), "ExceptionsHandler::StorageSize must be increased!");
644 static_assert(((StorageAlign % alignof(Impl)) == 0), "ExceptionsHandler::StorageAlign must be adjusted!");
645
646 // Create the implementation instance
647 new(&_storage)Impl();
648}
649
651{
652 // Delete the implementation instance
653 reinterpret_cast<Impl*>(&_storage)->~Impl();
654}
655
656void ExceptionsHandler::SetupHandler(const std::function<void (const SystemException&, const StackTrace&)>& handler) { GetInstance().impl().SetupHandler(handler); }
657void ExceptionsHandler::SetupProcess() { GetInstance().impl().SetupProcess(); }
658void ExceptionsHandler::SetupThread() { GetInstance().impl().SetupThread(); }
659
660} // namespace CppCommon
static void SetupProcess()
Setup exceptions handler for the current process.
static void SetupHandler(const std::function< void(const SystemException &, const StackTrace &)> &handler)
Setup new global exceptions handler function.
static void SetupThread()
Setup exceptions handler for the current thread.
static ExceptionsHandler & GetInstance()
Get singleton instance.
Definition singleton.h:61
Stack trace snapshot provider.
Definition stack_trace.h:33
System exception.
Definition exceptions.h:107
Static array countof definition.
#define throwex
Throw extended exception macro.
Definition exceptions.h:23
Exceptions handler definition.
Format string definition.
C++ Common project definitions.
std::string format(fmt::format_string< T... > pattern, T &&... args)
Format string.
Definition format.inl:12
auto resource(T handle, TCleaner cleaner)
Resource smart cleaner pattern.
Definition resource.h:43
constexpr size_t countof(const T(&)[N]) noexcept
Count of elements in static array.
Definition countof.h:16
Filesystem path definition.
Resource smart cleaner pattern definition.
#define __LOCATION__
Current source location macro.
Stack trace snapshot provider definition.
Timestamp definition.
Aligned storage validator definition.