diff --git a/components/common/cpp/include/ftl/exception.hpp b/components/common/cpp/include/ftl/exception.hpp index 07f7a366adf65cb7baea83624d8f1ff53a3cf848..43e303d9b803282408bea3096d1503b45597d031 100644 --- a/components/common/cpp/include/ftl/exception.hpp +++ b/components/common/cpp/include/ftl/exception.hpp @@ -7,29 +7,29 @@ namespace ftl { class Formatter { public: Formatter() {} - ~Formatter() {} + ~Formatter() {} - template <typename Type> - inline Formatter & operator << (const Type & value) - { - stream_ << value; - return *this; - } + template <typename Type> + inline Formatter & operator << (const Type & value) + { + stream_ << value; + return *this; + } - inline std::string str() const { return stream_.str(); } - inline operator std::string () const { return stream_.str(); } + inline std::string str() const { return stream_.str(); } + inline operator std::string () const { return stream_.str(); } - enum ConvertToString - { - to_str - }; - inline std::string operator >> (ConvertToString) { return stream_.str(); } + enum ConvertToString + { + to_str + }; + inline std::string operator >> (ConvertToString) { return stream_.str(); } private: - std::stringstream stream_; + std::stringstream stream_; - Formatter(const Formatter &); - Formatter & operator = (Formatter &); + Formatter(const Formatter &); + Formatter & operator = (Formatter &); }; class exception : public std::exception @@ -39,22 +39,30 @@ class exception : public std::exception explicit exception(const Formatter &msg); ~exception(); - const char * what () const throw () { + const char* what() const throw () { processed_ = true; - return msg_.c_str(); - } + return msg_.c_str(); + } - const char * trace () const throw () { - return trace_.c_str(); - } + std::string trace() const throw () { + return decode_backtrace(); + } void ignore() const { processed_ = true; } private: + std::string decode_backtrace() const; + std::string msg_; - std::string trace_; mutable bool processed_; + +#ifdef __GNUC__ + static const int TRACE_SIZE_MAX_ = 16; + void* trace_[TRACE_SIZE_MAX_]; + int trace_size_; +#endif }; + } #define FTL_Error(A) (ftl::exception(ftl::Formatter() << __FILE__ << ":" << __LINE__ << ": " << A)) diff --git a/components/common/cpp/src/exception.cpp b/components/common/cpp/src/exception.cpp index 46897adea1ef16ffa739a8fda961fd9d5fc6f70f..19edc276e8db8fd3dc2888bdec1a98e2b189f6e2 100644 --- a/components/common/cpp/src/exception.cpp +++ b/components/common/cpp/src/exception.cpp @@ -7,53 +7,52 @@ #include <execinfo.h> #include <dlfcn.h> #include <cxxabi.h> -#endif - -using ftl::exception; -using std::string; -static std::string demangle(const char* name) { +std::string demangle(const char* name) { if (!name) { return "[unknown symbol]"; } -#ifdef __GNUC__ int status; char* demangled = abi::__cxa_demangle(name, NULL, 0, &status); if (!demangled) { return std::string(name); } else { - auto result = string(demangled); + auto result = std::string(demangled); free(demangled); return result; } -#else - return std::string(name); -#endif } -static std::string addr_to_string(const void* addr) { +#endif + +using ftl::exception; +using std::string; + +string addr_to_string(const void* addr) { std::stringstream ss; ss << addr; return ss.str(); } -static std::string getBackTrace() { #ifdef __GNUC__ +string exception::decode_backtrace() const { string result; - void *trace[16]; - int trace_size = 0; - trace_size = backtrace(trace, 16); - char **messages = backtrace_symbols(trace, trace_size); + // backtrace_symbols() as fallback (no data from dladdr()) + char **messages = backtrace_symbols(trace_, trace_size_); - result = "[bt] Trace:\n"; + if (!messages) { + return string("[bt] no trace"); + } /* skip first stack frame (points here) */ - for (int i=2; i < trace_size; ++i) { - result += string("[bt] #") + std::to_string(i-1) + string(" "); + for (int i=1; i < trace_size_; ++i) { + result += string("[bt] #") + std::to_string(i-1) + + string(TRACE_SIZE_MAX_/10 - (i-1)/10, ' ') + + string(" "); Dl_info info; - if (dladdr(trace[i], &info) && info.dli_saddr) { + if (dladdr(trace_[i], &info) && info.dli_saddr) { auto name = demangle(info.dli_sname); string fname = info.dli_fname ? info.dli_fname: "[unknown file]"; @@ -71,25 +70,31 @@ static std::string getBackTrace() { free(messages); return result; +} -#elif _MSC_VER - return ""; #else - return ""; -#endif +string exception::decode_backtrace() const { + return string(); } +#endif exception::exception(const char *msg) : msg_(msg), processed_(false) { - trace_ = std::move(getBackTrace()); + #ifdef __GNUC__ + trace_size_ = backtrace(trace_, TRACE_SIZE_MAX_); + #endif } exception::exception(const ftl::Formatter &msg) : msg_(msg.str()), processed_(false) { - trace_ = std::move(getBackTrace()); + #ifdef __GNUC__ + trace_size_ = backtrace(trace_, TRACE_SIZE_MAX_); + #endif } exception::~exception() { if (!processed_) { LOG(ERROR) << "Unhandled exception: " << what(); - LOG(ERROR) << trace_; + #ifdef __GNUC__ + LOG(ERROR) << "Trace:\n" << decode_backtrace(); + #endif } }