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>
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
# include <execinfo.h>
|
||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
# include "icinga-version.h"
|
||||
|
@ -31,65 +29,6 @@
|
|||
|
||||
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.
|
||||
*
|
||||
|
@ -99,8 +38,6 @@ static void exception_handler(void)
|
|||
*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::set_terminate(exception_handler);
|
||||
|
||||
#ifndef _WIN32
|
||||
LTDL_SET_PRELOADED_SYMBOLS();
|
||||
#endif /* _WIN32 */
|
||||
|
@ -113,6 +50,9 @@ int main(int argc, char **argv)
|
|||
* in the base library. */
|
||||
Application::SetMainThread();
|
||||
|
||||
/* Install exception handlers to make debugging easier. */
|
||||
Application::InstallExceptionHandlers();
|
||||
|
||||
#ifdef ICINGA_PREFIX
|
||||
Application::SetPrefixDir(ICINGA_PREFIX);
|
||||
#endif /* ICINGA_PREFIX */
|
||||
|
|
|
@ -297,6 +297,20 @@ void Application::SigIntHandler(int signum)
|
|||
sa.sa_handler = SIG_DFL;
|
||||
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 */
|
||||
/**
|
||||
* Console control handler. Prepares the application for cleanly
|
||||
|
@ -316,6 +330,54 @@ BOOL WINAPI Application::CtrlHandler(DWORD type)
|
|||
}
|
||||
#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.
|
||||
*
|
||||
|
@ -335,7 +397,7 @@ int Application::Run(int argc, char **argv)
|
|||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sigaction(SIGPIPE, &sa, NULL);
|
||||
#else
|
||||
#else /* _WIN32 */
|
||||
SetConsoleCtrlHandler(&Application::CtrlHandler, TRUE);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ public:
|
|||
*/
|
||||
virtual int Main(const vector<String>& args) = 0;
|
||||
|
||||
static void InstallExceptionHandlers(void);
|
||||
|
||||
static void RequestShutdown(void);
|
||||
static void Terminate(int exitCode);
|
||||
|
||||
|
@ -89,10 +91,13 @@ private:
|
|||
|
||||
#ifndef _WIN32
|
||||
static void SigIntHandler(int signum);
|
||||
static void SigAbrtHandler(int signum);
|
||||
#else /* _WIN32 */
|
||||
static BOOL WINAPI CtrlHandler(DWORD type);
|
||||
#endif /* _WIN32 */
|
||||
|
||||
static void ExceptionHandler(void);
|
||||
|
||||
static void TimeWatchThreadProc(void);
|
||||
};
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include "i2-base.h"
|
||||
#include <mmatch.h>
|
||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||
# include <execinfo.h>
|
||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
|
@ -58,6 +61,56 @@ String Utility::GetTypeName(const type_info& ti)
|
|||
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.
|
||||
*/
|
||||
|
|
|
@ -33,6 +33,7 @@ class I2_BASE_API Utility
|
|||
public:
|
||||
static String DemangleSymbolName(const String& sym);
|
||||
static String GetTypeName(const type_info& ti);
|
||||
static bool PrintStacktrace(ostream& fp, int ignoreFrames = 0);
|
||||
|
||||
static void Daemonize(void);
|
||||
|
||||
|
|
Loading…
Reference in New Issue