mirror of https://github.com/Icinga/icinga2.git
Move exception_handler into libbase. Add handler for SIGABRT.
Fixes #3590
This commit is contained in:
parent
20958d0ba8
commit
ff0e6d91d2
|
@ -18,9 +18,7 @@
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#include <i2-icinga.h>
|
#include <i2-icinga.h>
|
||||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
|
||||||
# include <execinfo.h>
|
|
||||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include "icinga-version.h"
|
# include "icinga-version.h"
|
||||||
|
@ -31,65 +29,6 @@
|
||||||
|
|
||||||
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.
|
||||||
*
|
*
|
||||||
|
@ -99,8 +38,6 @@ static void exception_handler(void)
|
||||||
*/
|
*/
|
||||||
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 */
|
||||||
|
@ -113,6 +50,9 @@ int main(int argc, char **argv)
|
||||||
* in the base library. */
|
* in the base library. */
|
||||||
Application::SetMainThread();
|
Application::SetMainThread();
|
||||||
|
|
||||||
|
/* Install exception handlers to make debugging easier. */
|
||||||
|
Application::InstallExceptionHandlers();
|
||||||
|
|
||||||
#ifdef ICINGA_PREFIX
|
#ifdef ICINGA_PREFIX
|
||||||
Application::SetPrefixDir(ICINGA_PREFIX);
|
Application::SetPrefixDir(ICINGA_PREFIX);
|
||||||
#endif /* ICINGA_PREFIX */
|
#endif /* ICINGA_PREFIX */
|
||||||
|
|
|
@ -297,6 +297,20 @@ void Application::SigIntHandler(int signum)
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sigaction(SIGINT, &sa, NULL);
|
sigaction(SIGINT, &sa, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signal handler for SIGABRT. Helps with debugging assert()s.
|
||||||
|
*
|
||||||
|
* @param signum The signal number.
|
||||||
|
*/
|
||||||
|
void Application::SigAbrtHandler(int signum)
|
||||||
|
{
|
||||||
|
assert(signum == SIGABRT);
|
||||||
|
|
||||||
|
std::cerr << "Caught SIGABRT." << std::endl;
|
||||||
|
|
||||||
|
Utility::PrintStacktrace(std::cerr, 1);
|
||||||
|
}
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
/**
|
/**
|
||||||
* Console control handler. Prepares the application for cleanly
|
* Console control handler. Prepares the application for cleanly
|
||||||
|
@ -316,6 +330,54 @@ BOOL WINAPI Application::CtrlHandler(DWORD type)
|
||||||
}
|
}
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for unhandled exceptions.
|
||||||
|
*/
|
||||||
|
void Application::ExceptionHandler(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Utility::PrintStacktrace(std::cerr, 1);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, sizeof(sa), 0);
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs the exception handlers.
|
||||||
|
*/
|
||||||
|
void Application::InstallExceptionHandlers(void)
|
||||||
|
{
|
||||||
|
std::set_terminate(&Application::ExceptionHandler);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_handler = &Application::SigAbrtHandler;
|
||||||
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the application.
|
* Runs the application.
|
||||||
*
|
*
|
||||||
|
@ -335,7 +397,7 @@ int Application::Run(int argc, char **argv)
|
||||||
|
|
||||||
sa.sa_handler = SIG_IGN;
|
sa.sa_handler = SIG_IGN;
|
||||||
sigaction(SIGPIPE, &sa, NULL);
|
sigaction(SIGPIPE, &sa, NULL);
|
||||||
#else
|
#else /* _WIN32 */
|
||||||
SetConsoleCtrlHandler(&Application::CtrlHandler, TRUE);
|
SetConsoleCtrlHandler(&Application::CtrlHandler, TRUE);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual int Main(const vector<String>& args) = 0;
|
virtual int Main(const vector<String>& args) = 0;
|
||||||
|
|
||||||
|
static void InstallExceptionHandlers(void);
|
||||||
|
|
||||||
static void RequestShutdown(void);
|
static void RequestShutdown(void);
|
||||||
static void Terminate(int exitCode);
|
static void Terminate(int exitCode);
|
||||||
|
|
||||||
|
@ -89,10 +91,13 @@ private:
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static void SigIntHandler(int signum);
|
static void SigIntHandler(int signum);
|
||||||
|
static void SigAbrtHandler(int signum);
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
static BOOL WINAPI CtrlHandler(DWORD type);
|
static BOOL WINAPI CtrlHandler(DWORD type);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
static void ExceptionHandler(void);
|
||||||
|
|
||||||
static void TimeWatchThreadProc(void);
|
static void TimeWatchThreadProc(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
#include "i2-base.h"
|
#include "i2-base.h"
|
||||||
#include <mmatch.h>
|
#include <mmatch.h>
|
||||||
|
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||||
|
# include <execinfo.h>
|
||||||
|
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
@ -58,6 +61,56 @@ String Utility::GetTypeName(const type_info& ti)
|
||||||
return DemangleSymbolName(ti.name());
|
return DemangleSymbolName(ti.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a stacktrace to the specified stream.
|
||||||
|
*
|
||||||
|
* @param fp The stream.
|
||||||
|
* @param ignoreFrames The number of stackframes to ignore (in addition to
|
||||||
|
* the one this function is executing in).
|
||||||
|
* @returns true if the stacktrace was printed, false otherwise.
|
||||||
|
*/
|
||||||
|
bool Utility::PrintStacktrace(ostream& fp, int ignoreFrames)
|
||||||
|
{
|
||||||
|
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||||
|
void *frames[50];
|
||||||
|
int framecount = backtrace(frames, sizeof(frames) / sizeof(frames[0]));
|
||||||
|
|
||||||
|
char **messages = backtrace_symbols(frames, framecount);
|
||||||
|
|
||||||
|
fp << std::endl << "Stacktrace:" << std::endl;
|
||||||
|
|
||||||
|
for (int i = ignoreFrames + 1; 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fp << "\t(" << i - ignoreFrames - 1 << ") " << message << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(messages);
|
||||||
|
|
||||||
|
fp << std::endl;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
return false;
|
||||||
|
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detaches from the controlling terminal.
|
* Detaches from the controlling terminal.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,6 +33,7 @@ class I2_BASE_API Utility
|
||||||
public:
|
public:
|
||||||
static String DemangleSymbolName(const String& sym);
|
static String DemangleSymbolName(const String& sym);
|
||||||
static String GetTypeName(const type_info& ti);
|
static String GetTypeName(const type_info& ti);
|
||||||
|
static bool PrintStacktrace(ostream& fp, int ignoreFrames = 0);
|
||||||
|
|
||||||
static void Daemonize(void);
|
static void Daemonize(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue