Home | History | Annotate | Download | only in support
      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