-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathprettifysegfault.h
More file actions
90 lines (81 loc) · 3.16 KB
/
prettifysegfault.h
File metadata and controls
90 lines (81 loc) · 3.16 KB
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
#ifndef PRETTIFYSEGFAULT_H
#define PRETTIFYSEGFAULT_H
#include <boost/exception/all.hpp>
/**
* @brief The PrettifySegfault class should attempt to capture any null-pointer
* exception (SIGSEGV and SIGILL) in the program, log a backtrace, and then
* throw a regular C++ exception from the function causing the signal.
*
* When you attempt to recover from segfaults,
* you are playing with fire.
*
* Once a segfault has been detected without a crash,
* you should restart the process. It is likely that a segfault
* will still crash the process, but there should at least be
* some info in the log.
*
* While at it, PrettifySegfault::setup() sets up logging of all other signal
* types as well if they are detected, but without taking any further action.
* (except SIGCHLD which is ignored)
*
*
* Windows specific
* Backtraces works in 64-bit windows on 64-bit builds but not on 32-bit bulids (WOW64).
*
*
* GCC/CLANG specific information below
* (these concerns does not apply to MSC where the implementation is based on SEH)
*
* Throwing from within a signal handler is undefined behavior. This
* implementation is based on a hack to rewrite the function stack. Please
* refer to 'feepingcreature' for the full explanation at
* http://feepingcreature.github.io/handling.html
*
* However, this doesn't always work. See note number 4 at the url above. And
* it returns immediately from the signalling function without unwinding
* the scope and thus break the RAII assumption that a destructor will
* always be called. I.e leaking resources and potentially leaving the
* process in an unconsistent state (and this is in addition to any harm that
* happened before the original SIGSEGV/SIGILL was detected).
*
* So don't rely on this class, it's not a safety net, it merely serves to
* quickly indicate the location of a severe error when it occurs.
*/
class PrettifySegfault
{
public:
enum SignalHandlingState {
normal_execution,
doing_signal_handling
};
/**
* @brief setup enables PrettifySegfault.
*/
static void setup();
/**
* @return If the process is in the state of signal handling you
* should proceed to exit the process.
*/
static SignalHandlingState signal_handling_state ();
static bool has_caught_any_signal ();
/**
* @brief PrettifySegfaultDirectPrint makes the signal handler write info
* to stdout as soon as the signal is caught. Default enable=true.
* @param enable
*/
static void EnableDirectPrint(bool enable);
/**
* @brief test will cause a segfault. This will put the process in
* signal_handling_state and prevent further signals from being caught.
* Such signals will instead halt the process.
*/
static void test();
};
class signal_exception: virtual public boost::exception, virtual public std::exception {
public:
typedef boost::error_info<struct signal, int> signal;
typedef boost::error_info<struct signalname, const char*> signalname;
typedef boost::error_info<struct signaldesc, const char*> signaldesc;
};
class segfault_sigill_exception: public signal_exception {};
#endif // PRETTIFYSEGFAULT_H