artdaq_core  v3_06_01
ExceptionStackTrace.hh
1 #ifndef EXCEPTIONSTACKTRACE_H
2 #define EXCEPTIONSTACKTRACE_H
3 
4 #include <memory>
5 #include <mutex>
6 #include <string>
7 #include <thread>
8 #include <unordered_map>
9 #include <vector>
10 
11 extern "C" {
12 
16 #ifndef __clang__
17 typedef void(__cxa_throw_t)(void*, void*, void (*)(void*));
18 void __cxa_throw(void*, void*, void (*)(void*));
19 #else //__clang__
20 typedef __attribute__((noreturn)) void(__cxa_throw_t)(void*, std::type_info*, void (*)(void*));
21 __attribute__((noreturn)) void __cxa_throw(void*, std::type_info*, void (*)(void*));
22 #endif //__clang__
23 }
24 
25 namespace artdaq::debug {
26 
30 class Trace
31 {
32 public:
38  explicit Trace(size_t index, std::string symbol)
39  : index_{index}, symbol_{std::move(symbol)}, address_{0}, filename_{"unresolved"}, function_{"unresolved"}, offset_{0}
40  {
41  }
42 
43  //default
44  Trace(Trace&&) = default;
45 
46  //deleted
47  Trace(const Trace&) = delete;
48  Trace& operator=(const Trace&) = delete;
49  Trace& operator=(Trace&&) = delete;
50 
54  std::string print() const;
55 
59  void resolve();
60 
61 private:
65  size_t index_;
69  std::string symbol_;
73  uintptr_t address_;
77  std::string filename_;
81  std::string function_;
85  uintptr_t offset_;
86 };
87 
88 inline std::ostream& operator<<(std::ostream& os, Trace const& trace)
89 {
90  os << trace.print();
91  return os;
92 }
93 
98 {
99 public:
100  using traces_t = std::vector<Trace>;
101 
106  explicit StackTrace(std::string type_name);
107 
111  std::string print() const;
115  void resolve();
116 
117  //default
118  StackTrace(StackTrace&&) = default;
119  StackTrace& operator=(StackTrace&&) = default;
120 
121  //deleted
122  StackTrace(const StackTrace&) = delete;
123  StackTrace& operator=(const StackTrace&) = delete;
124 
128  static std::string demangle(std::string const& symbol);
129 
130 private:
134  std::string type_name_;
138  std::unique_ptr<traces_t> traces_uptr_;
142  int size_;
146  void* frames_[1024];
147 };
148 
149 inline std::ostream& operator<<(std::ostream& os, StackTrace const& stack_trace)
150 {
151  os << stack_trace.print();
152  return os;
153 }
154 
159 {
160 public:
161  using stacktrace_map_t = std::unordered_map<std::thread::id, StackTrace>;
162 
167  : stack_traces_{}, stack_traces_mutex_{} {}
168 
169  //deleted
170  StackTraceCollector(const StackTraceCollector&) = delete;
171  StackTraceCollector& operator=(const StackTraceCollector&) = delete;
173  StackTraceCollector& operator=(StackTraceCollector&&) = delete;
174 
178  template<typename... Args>
179  void collect_stacktrace(Args&&... args)
180  {
181  std::lock_guard<std::mutex> lg(stack_traces_mutex_);
182  stack_traces_.insert_or_assign(std::this_thread::get_id(), StackTrace(std::forward<Args>(args)...));
183  }
184 
188  std::string print_stacktrace()
189  {
190  try
191  {
192  std::lock_guard<std::mutex> lg(stack_traces_mutex_);
193  auto& stack_trace = stack_traces_.at(std::this_thread::get_id());
194  stack_trace.resolve();
195  return stack_trace.print();
196  }
197  catch (...)
198  {
199  return "Error: possibly corrupt stack.";
200  }
201  }
202 
203 private:
207  stacktrace_map_t stack_traces_;
208 
212  mutable std::mutex stack_traces_mutex_;
213 };
214 
215 StackTraceCollector& getStackTraceCollector();
216 } // namespace artdaq::debug
217 #endif /* #ifndef EXCEPTIONSTACKTRACE_H*/
static std::string demangle(std::string const &symbol)
Demangles backtrace symbols.
Represents the entire stack trace message.
Trace(size_t index, std::string symbol)
Constructor.
void resolve()
Reads and demangles backtrace symbols.
StackTrace(std::string type_name)
Constructor.
std::ostream & operator<<(std::ostream &os, Fragment const &f)
Prints the given Fragment to the stream.
Definition: Fragment.hh:1284
void resolve()
Reads and demangles backtrace symbols.
Collects stack traces from different threads.
std::string print() const
Produces a stack trace summary.
std::string print_stacktrace()
Produces a stack trace summary.
void collect_stacktrace(Args &&...args)
Adds a stacktrace to the stack_traces_ map.
Represents one line of the stack trace message.
std::string print() const
Produces a one-line summary.