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