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
-DICINGA_LIBDIR="\"$(pkglibdir)\""
icinga2_LDFLAGS = \
- $(BOOST_LDFLAGS)
+ $(BOOST_LDFLAGS) \
+ -export-dynamic
icinga2_LDADD = \
$(LIBLTDL) \
******************************************************************************/
#include <i2-icinga.h>
+#include <execinfo.h>
#ifndef _WIN32
# include "icinga-version.h"
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.
*
*/
int main(int argc, char **argv)
{
+ std::set_terminate(exception_handler);
+
#ifndef _WIN32
LTDL_SET_PRELOADED_SYMBOLS();
#endif /* _WIN32 */
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();
bool I2_EXPORT Utility::m_SSLInitialized = false;
/**
- * Returns a human-readable type name of a type_info object.
+ * Demangles a symbol name.
*
- * @param ti A type_info object.
- * @returns The type name of the object.
+ * @param sym The symbol name.
+ * @returns A human-readable version of the symbol name.
*/
-String Utility::GetTypeName(const type_info& ti)
+String Utility::DemangleSymbolName(const String& sym)
{
- String klass = ti.name();
+ String result = sym;
#ifdef HAVE_GCC_ABI_DEMANGLE
int status;
- char *realname = abi::__cxa_demangle(klass.CStr(), 0, 0, &status);
+ char *realname = abi::__cxa_demangle(sym.CStr(), 0, 0, &status);
if (realname != NULL) {
- klass = String(realname);
+ result = String(realname);
free(realname);
}
#endif /* HAVE_GCC_ABI_DEMANGLE */
- return klass;
+ return result;
}
+/**
+ * Returns a human-readable type name of a type_info object.
+ *
+ * @param ti A type_info object.
+ * @returns The type name of the object.
+ */
+String Utility::GetTypeName(const type_info& ti)
+{
+ return DemangleSymbolName(ti.name());
+}
/**
* Detaches from the controlling terminal.
class I2_BASE_API Utility
{
public:
+ static String DemangleSymbolName(const String& sym);
static String GetTypeName(const type_info& ti);
static void Daemonize(void);