blob: 6627b35eb30d1a60c42719b8e744f8780acb89d2 [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
Eric Fiselierfb946da2016-07-18 03:00:09 +000014 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
Eric Fiselierfa1f6132016-04-15 23:27:27 +000019 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
32inline Checkpoint& globalCheckpoint() {
33 static Checkpoint C;
34 return C;
35}
36
37inline void clearCheckpoint() {
Eric Fiselierfb946da2016-07-18 03:00:09 +000038 globalCheckpoint() = Checkpoint();
Eric Fiselierfa1f6132016-04-15 23:27:27 +000039}
40
Eric Fiselier1f4231f2016-04-28 22:28:23 +000041#if defined(__GNUC__)
42#define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__
43#else
44#define CHECKPOINT_FUNCTION_NAME __func__
45#endif
46
Eric Fiselierfb946da2016-07-18 03:00:09 +000047#define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg);
Eric Fiselierfa1f6132016-04-15 23:27:27 +000048
49inline 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
58inline 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
71static bool initDummy = initCheckpointHandler();
72
73#endif