Make exception messages more verbose.

This commit is contained in:
Gunnar Beutner 2012-09-27 09:38:28 +02:00
parent 74a3bca0f6
commit c5479057f7
6 changed files with 91 additions and 28 deletions

View File

@ -64,6 +64,7 @@ AC_CHECK_LIB(m, floor)
AC_CHECK_LIB(socket, getsockname) AC_CHECK_LIB(socket, getsockname)
AC_CHECK_LIB(ws2_32, getsockname) AC_CHECK_LIB(ws2_32, getsockname)
AC_CHECK_LIB(shlwapi, PathRemoveFileSpecA) AC_CHECK_LIB(shlwapi, PathRemoveFileSpecA)
AC_CHECK_FUNCS([backtrace_symbols])
AC_CONFIG_FILES([ AC_CONFIG_FILES([
Makefile Makefile

View File

@ -21,7 +21,8 @@ icinga2_CPPFLAGS = \
-DICINGA_LIBDIR="\"$(pkglibdir)\"" -DICINGA_LIBDIR="\"$(pkglibdir)\""
icinga2_LDFLAGS = \ icinga2_LDFLAGS = \
$(BOOST_LDFLAGS) $(BOOST_LDFLAGS) \
-export-dynamic
icinga2_LDADD = \ icinga2_LDADD = \
$(LIBLTDL) \ $(LIBLTDL) \

View File

@ -18,6 +18,7 @@
******************************************************************************/ ******************************************************************************/
#include <i2-icinga.h> #include <i2-icinga.h>
#include <execinfo.h>
#ifndef _WIN32 #ifndef _WIN32
# include "icinga-version.h" # include "icinga-version.h"
@ -28,6 +29,65 @@
using namespace icinga; 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 = "<unknown function>";
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. * Entry point for the Icinga application.
* *
@ -37,6 +97,8 @@ using namespace icinga;
*/ */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
std::set_terminate(exception_handler);
#ifndef _WIN32 #ifndef _WIN32
LTDL_SET_PRELOADED_SYMBOLS(); LTDL_SET_PRELOADED_SYMBOLS();
#endif /* _WIN32 */ #endif /* _WIN32 */

View File

@ -338,19 +338,7 @@ int Application::Run(int argc, char **argv)
DynamicObject::BeginTx(); DynamicObject::BeginTx();
if (IsDebugging()) { result = Main(m_Arguments);
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;
}
}
DynamicObject::FinishTx(); DynamicObject::FinishTx();
DynamicObject::DeactivateObjects(); DynamicObject::DeactivateObjects();

View File

@ -24,6 +24,29 @@ using namespace icinga;
bool I2_EXPORT Utility::m_SSLInitialized = false; 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. * 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 Utility::GetTypeName(const type_info& ti)
{ {
String klass = ti.name(); return DemangleSymbolName(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;
} }
/** /**
* Detaches from the controlling terminal. * Detaches from the controlling terminal.
*/ */

View File

@ -31,6 +31,7 @@ namespace icinga
class I2_BASE_API Utility class I2_BASE_API Utility
{ {
public: public:
static String DemangleSymbolName(const String& sym);
static String GetTypeName(const type_info& ti); static String GetTypeName(const type_info& ti);
static void Daemonize(void); static void Daemonize(void);