$treeview $search $mathjax $extrastylesheet
artdaq_core
v3_06_01
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #ifndef EXCEPTIONSTACKTRACE_H 00002 #define EXCEPTIONSTACKTRACE_H 00003 00004 #include <memory> 00005 #include <mutex> 00006 #include <string> 00007 #include <thread> 00008 #include <unordered_map> 00009 #include <vector> 00010 00011 extern "C" { 00012 00016 #ifndef __clang__ 00017 typedef void(__cxa_throw_t)(void*, void*, void (*)(void*)); 00018 void __cxa_throw(void*, void*, void (*)(void*)); 00019 #else //__clang__ 00020 typedef __attribute__((noreturn)) void(__cxa_throw_t)(void*, std::type_info*, void (*)(void*)); 00021 __attribute__((noreturn)) void __cxa_throw(void*, std::type_info*, void (*)(void*)); 00022 #endif //__clang__ 00023 } 00024 00025 namespace artdaq::debug { 00026 00030 class Trace 00031 { 00032 public: 00038 explicit Trace(size_t index, std::string symbol) 00039 : index_{index}, symbol_{std::move(symbol)}, address_{0}, filename_{"unresolved"}, function_{"unresolved"}, offset_{0} 00040 { 00041 } 00042 00043 //default 00044 Trace(Trace&&) = default; 00045 00046 //deleted 00047 Trace(const Trace&) = delete; 00048 Trace& operator=(const Trace&) = delete; 00049 Trace& operator=(Trace&&) = delete; 00050 00054 std::string print() const; 00055 00059 void resolve(); 00060 00061 private: 00065 size_t index_; 00069 std::string symbol_; 00073 uintptr_t address_; 00077 std::string filename_; 00081 std::string function_; 00085 uintptr_t offset_; 00086 }; 00087 00088 inline std::ostream& operator<<(std::ostream& os, Trace const& trace) 00089 { 00090 os << trace.print(); 00091 return os; 00092 } 00093 00097 class StackTrace 00098 { 00099 public: 00100 using traces_t = std::vector<Trace>; 00101 00106 explicit StackTrace(std::string type_name); 00107 00111 std::string print() const; 00115 void resolve(); 00116 00117 //default 00118 StackTrace(StackTrace&&) = default; 00119 StackTrace& operator=(StackTrace&&) = default; 00120 00121 //deleted 00122 StackTrace(const StackTrace&) = delete; 00123 StackTrace& operator=(const StackTrace&) = delete; 00124 00128 static std::string demangle(std::string const& symbol); 00129 00130 private: 00134 std::string type_name_; 00138 std::unique_ptr<traces_t> traces_uptr_; 00142 int size_; 00146 void* frames_[1024]; 00147 }; 00148 00149 inline std::ostream& operator<<(std::ostream& os, StackTrace const& stack_trace) 00150 { 00151 os << stack_trace.print(); 00152 return os; 00153 } 00154 00158 class StackTraceCollector 00159 { 00160 public: 00161 using stacktrace_map_t = std::unordered_map<std::thread::id, StackTrace>; 00162 00166 StackTraceCollector() 00167 : stack_traces_{}, stack_traces_mutex_{} {} 00168 00169 //deleted 00170 StackTraceCollector(const StackTraceCollector&) = delete; 00171 StackTraceCollector& operator=(const StackTraceCollector&) = delete; 00172 StackTraceCollector(StackTraceCollector&&) = delete; 00173 StackTraceCollector& operator=(StackTraceCollector&&) = delete; 00174 00178 template<typename... Args> 00179 void collect_stacktrace(Args&&... args) 00180 { 00181 std::lock_guard<std::mutex> lg(stack_traces_mutex_); 00182 stack_traces_.insert_or_assign(std::this_thread::get_id(), StackTrace(std::forward<Args>(args)...)); 00183 } 00184 00188 std::string print_stacktrace() 00189 { 00190 try 00191 { 00192 std::lock_guard<std::mutex> lg(stack_traces_mutex_); 00193 auto& stack_trace = stack_traces_.at(std::this_thread::get_id()); 00194 stack_trace.resolve(); 00195 return stack_trace.print(); 00196 } 00197 catch (...) 00198 { 00199 return "Error: possibly corrupt stack."; 00200 } 00201 } 00202 00203 private: 00207 stacktrace_map_t stack_traces_; 00208 00212 mutable std::mutex stack_traces_mutex_; 00213 }; 00214 00215 StackTraceCollector& getStackTraceCollector(); 00216 } // namespace artdaq::debug 00217 #endif /* #ifndef EXCEPTIONSTACKTRACE_H*/