From c5479057f7285a7a6a06b625314b85bdf8f0aa79 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Thu, 27 Sep 2012 09:38:28 +0200 Subject: [PATCH] Make exception messages more verbose. --- configure.ac | 1 + icinga-app/Makefile.am | 3 +- icinga-app/icinga.cpp | 62 ++++++++++++++++++++++++++++++++++++++++ lib/base/application.cpp | 14 +-------- lib/base/utility.cpp | 38 +++++++++++++++--------- lib/base/utility.h | 1 + 6 files changed, 91 insertions(+), 28 deletions(-) diff --git a/configure.ac b/configure.ac index be72913ac..2f49a9f0a 100644 --- a/configure.ac +++ b/configure.ac @@ -64,6 +64,7 @@ AC_CHECK_LIB(m, floor) AC_CHECK_LIB(socket, getsockname) AC_CHECK_LIB(ws2_32, getsockname) AC_CHECK_LIB(shlwapi, PathRemoveFileSpecA) +AC_CHECK_FUNCS([backtrace_symbols]) AC_CONFIG_FILES([ Makefile diff --git a/icinga-app/Makefile.am b/icinga-app/Makefile.am index fb27b3287..8c7a64dfa 100644 --- a/icinga-app/Makefile.am +++ b/icinga-app/Makefile.am @@ -21,7 +21,8 @@ icinga2_CPPFLAGS = \ -DICINGA_LIBDIR="\"$(pkglibdir)\"" icinga2_LDFLAGS = \ - $(BOOST_LDFLAGS) + $(BOOST_LDFLAGS) \ + -export-dynamic icinga2_LDADD = \ $(LIBLTDL) \ diff --git a/icinga-app/icinga.cpp b/icinga-app/icinga.cpp index f59777501..af2ca239f 100644 --- a/icinga-app/icinga.cpp +++ b/icinga-app/icinga.cpp @@ -18,6 +18,7 @@ ******************************************************************************/ #include +#include #ifndef _WIN32 # include "icinga-version.h" @@ -28,6 +29,65 @@ using namespace icinga; +/** + * Handler for unhandled exceptions. + * + */ +static void exception_handler(void) +{ + static bool rethrow = true; + + try { + rethrow = false; + throw; + } catch (const std::exception& ex) { + std::cerr << std::endl; + std::cerr << "Unhandled exception of type " + << Utility::GetTypeName(typeid(ex)) + << std::endl; + std::cerr << "Diagnostic Information: " + << ex.what() + << std::endl; + } + +#ifdef HAVE_BACKTRACE_SYMBOLS + void *frames[50]; + int framecount = backtrace(frames, sizeof(frames) / sizeof(frames[0])); + + char **messages = backtrace_symbols(frames, framecount); + + std::cerr << std::endl << "Stacktrace:" << std::endl; + + for (int i = 0; i < framecount && messages != NULL; ++i) { + String message = messages[i]; + + char *sym_begin = strchr(messages[i], '('); + + if (sym_begin != NULL) { + char *sym_end = strchr(sym_begin, '+'); + + if (sym_end != NULL) { + String sym = String(sym_begin + 1, sym_end); + String sym_demangled = Utility::DemangleSymbolName(sym); + + if (sym_demangled.IsEmpty()) + sym_demangled = ""; + + message = String(messages[i], sym_begin) + ": " + sym_demangled + " (" + String(sym_end); + } + } + + std::cerr << "\t(" << i << ") " << message << std::endl; + } + + free(messages); + + std::cerr << std::endl; +#endif /* HAVE_BACKTRACE_SYMBOLS */ + + abort(); +} + /** * Entry point for the Icinga application. * @@ -37,6 +97,8 @@ using namespace icinga; */ int main(int argc, char **argv) { + std::set_terminate(exception_handler); + #ifndef _WIN32 LTDL_SET_PRELOADED_SYMBOLS(); #endif /* _WIN32 */ diff --git a/lib/base/application.cpp b/lib/base/application.cpp index 5a423b804..5071be06f 100644 --- a/lib/base/application.cpp +++ b/lib/base/application.cpp @@ -338,19 +338,7 @@ int Application::Run(int argc, char **argv) DynamicObject::BeginTx(); - if (IsDebugging()) { - result = Main(m_Arguments); - } else { - try { - result = Main(m_Arguments); - } catch (const exception& ex) { - Logger::Write(LogCritical, "base", "---"); - Logger::Write(LogCritical, "base", "Exception: " + Utility::GetTypeName(typeid(ex))); - Logger::Write(LogCritical, "base", "Message: " + String(ex.what())); - - result = EXIT_FAILURE; - } - } + result = Main(m_Arguments); DynamicObject::FinishTx(); DynamicObject::DeactivateObjects(); diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index e388739b6..21aff8b36 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -24,6 +24,29 @@ using namespace icinga; bool I2_EXPORT Utility::m_SSLInitialized = false; +/** + * Demangles a symbol name. + * + * @param sym The symbol name. + * @returns A human-readable version of the symbol name. + */ +String Utility::DemangleSymbolName(const String& sym) +{ + String result = sym; + +#ifdef HAVE_GCC_ABI_DEMANGLE + int status; + char *realname = abi::__cxa_demangle(sym.CStr(), 0, 0, &status); + + if (realname != NULL) { + result = String(realname); + free(realname); + } +#endif /* HAVE_GCC_ABI_DEMANGLE */ + + return result; +} + /** * Returns a human-readable type name of a type_info object. * @@ -32,22 +55,9 @@ bool I2_EXPORT Utility::m_SSLInitialized = false; */ String Utility::GetTypeName(const type_info& ti) { - String klass = ti.name(); - -#ifdef HAVE_GCC_ABI_DEMANGLE - int status; - char *realname = abi::__cxa_demangle(klass.CStr(), 0, 0, &status); - - if (realname != NULL) { - klass = String(realname); - free(realname); - } -#endif /* HAVE_GCC_ABI_DEMANGLE */ - - return klass; + return DemangleSymbolName(ti.name()); } - /** * Detaches from the controlling terminal. */ diff --git a/lib/base/utility.h b/lib/base/utility.h index b1f5d00ea..50c97ce3f 100644 --- a/lib/base/utility.h +++ b/lib/base/utility.h @@ -31,6 +31,7 @@ namespace icinga class I2_BASE_API Utility { public: + static String DemangleSymbolName(const String& sym); static String GetTypeName(const type_info& ti); static void Daemonize(void);