blob: eea78efc39c3c61a996e414595670fba9f5456ad [file] [log] [blame]
Eric Fiselierfa1f6132016-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
36#define CHECKPOINT(msg) globalCheckpoint() = Checkpoint{__FILE__, __PRETTY_FUNCTION__, __LINE__, msg}
37
38inline void checkpointSignalHandler(int signal) {
39 if (signal == SIGABRT) {
40 globalCheckpoint().print(std::cerr);
41 } else {
42 std::cerr << "Unexpected signal " << signal << " received\n";
43 }
44 std::_Exit(EXIT_FAILURE);
45}
46
47inline bool initCheckpointHandler() {
48 typedef void(*HandlerT)(int);
49 static bool isInit = false;
50 if (isInit) return true;
51 HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler);
52 if (prev_h == SIG_ERR) {
53 std::cerr << "Setup failed.\n";
54 std::_Exit(EXIT_FAILURE);
55 }
56 isInit = true;
57 return false;
58}
59
60static bool initDummy = initCheckpointHandler();
61
62#endif