1 #ifndef SUPPORT_ASSERT_CHECKPOINT_H 2 #define SUPPORT_ASSERT_CHECKPOINT_H 3 4 #include <csignal> 5 #include <iostream> 6 #include <cstdlib> 7 8 struct Checkpoint { 9 const char* file; 10 const char* func; 11 int line; 12 const char* msg; 13 14 Checkpoint() : file(nullptr), func(nullptr), line(-1), msg(nullptr) {} 15 Checkpoint(const char* xfile, const char* xfunc, int xline, const char* xmsg) 16 : file(xfile), func(xfunc), line(xline), msg(xmsg) 17 {} 18 19 template <class Stream> 20 void print(Stream& s) const { 21 if (!file) { 22 s << "NO CHECKPOINT\n"; 23 return; 24 } 25 s << file << ":" << line << " " << func << ": Checkpoint"; 26 if (msg) 27 s << " '" << msg << "'"; 28 s << std::endl; 29 } 30 }; 31 32 inline Checkpoint& globalCheckpoint() { 33 static Checkpoint C; 34 return C; 35 } 36 37 inline void clearCheckpoint() { 38 globalCheckpoint() = Checkpoint(); 39 } 40 41 #if defined(__GNUC__) 42 #define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__ 43 #else 44 #define CHECKPOINT_FUNCTION_NAME __func__ 45 #endif 46 47 #define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg); 48 49 inline void checkpointSignalHandler(int signal) { 50 if (signal == SIGABRT) { 51 globalCheckpoint().print(std::cerr); 52 } else { 53 std::cerr << "Unexpected signal " << signal << " received\n"; 54 } 55 std::_Exit(EXIT_FAILURE); 56 } 57 58 inline bool initCheckpointHandler() { 59 typedef void(*HandlerT)(int); 60 static bool isInit = false; 61 if (isInit) return true; 62 HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler); 63 if (prev_h == SIG_ERR) { 64 std::cerr << "Setup failed.\n"; 65 std::_Exit(EXIT_FAILURE); 66 } 67 isInit = true; 68 return false; 69 } 70 71 static bool initDummy = initCheckpointHandler(); 72 73 #endif 74