mirror of https://github.com/Icinga/icinga2.git
Implemented stacktrace support for Windows.
This commit is contained in:
parent
5a166f83d7
commit
fa3f01667f
|
@ -58,6 +58,8 @@ libbase_la_SOURCES = \
|
||||||
scripttask.h \
|
scripttask.h \
|
||||||
socket.cpp \
|
socket.cpp \
|
||||||
socket.h \
|
socket.h \
|
||||||
|
stacktrace.cpp \
|
||||||
|
stacktrace.h \
|
||||||
stdiostream.cpp \
|
stdiostream.cpp \
|
||||||
stdiostream.h \
|
stdiostream.h \
|
||||||
stream.cpp \
|
stream.cpp \
|
||||||
|
|
|
@ -308,10 +308,12 @@ void Application::SigAbrtHandler(int signum)
|
||||||
{
|
{
|
||||||
assert(signum == SIGABRT);
|
assert(signum == SIGABRT);
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = SIG_DFL;
|
sa.sa_handler = SIG_DFL;
|
||||||
sigaction(SIGABRT, &sa, NULL);
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
std::cerr << "Caught SIGABRT." << std::endl;
|
std::cerr << "Caught SIGABRT." << std::endl;
|
||||||
|
|
||||||
|
@ -358,13 +360,27 @@ void Application::ExceptionHandler(void)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utility::PrintStacktrace(std::cerr, 1);
|
StackTrace trace;
|
||||||
|
trace.Print(std::cerr, 1);
|
||||||
|
|
||||||
DisplayBugMessage();
|
DisplayBugMessage();
|
||||||
|
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
|
||||||
|
{
|
||||||
|
std::cerr << "Unhandled SEH exception." << std::endl;
|
||||||
|
|
||||||
|
StackTrace trace(exi);
|
||||||
|
trace.Print(std::cerr, 1);
|
||||||
|
|
||||||
|
DisplayBugMessage();
|
||||||
|
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
#endif /* _WIN32
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs the exception handlers.
|
* Installs the exception handlers.
|
||||||
|
@ -378,6 +394,8 @@ void Application::InstallExceptionHandlers(void)
|
||||||
memset(&sa, 0, sizeof(sa));
|
memset(&sa, 0, sizeof(sa));
|
||||||
sa.sa_handler = &Application::SigAbrtHandler;
|
sa.sa_handler = &Application::SigAbrtHandler;
|
||||||
sigaction(SIGABRT, &sa, NULL);
|
sigaction(SIGABRT, &sa, NULL);
|
||||||
|
#else /* _WIN32 */
|
||||||
|
SetUnhandledExceptionFilter(&Application::SEHUnhandledExceptionFilter);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,13 +101,14 @@ 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);
|
||||||
|
static LONG WINAPI SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
static void DisplayBugMessage(void);
|
static void DisplayBugMessage(void);
|
||||||
|
|
||||||
|
static void SigAbrtHandler(int signum);
|
||||||
static void ExceptionHandler(void);
|
static void ExceptionHandler(void);
|
||||||
|
|
||||||
static void TimeWatchThreadProc(void);
|
static void TimeWatchThreadProc(void);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="application.cpp" />
|
<ClCompile Include="application.cpp" />
|
||||||
|
<ClCompile Include="attribute.cpp" />
|
||||||
<ClCompile Include="component.cpp" />
|
<ClCompile Include="component.cpp" />
|
||||||
<ClCompile Include="connection.cpp" />
|
<ClCompile Include="connection.cpp" />
|
||||||
<ClCompile Include="convert.cpp" />
|
<ClCompile Include="convert.cpp" />
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
<ClCompile Include="scriptfunction.cpp" />
|
<ClCompile Include="scriptfunction.cpp" />
|
||||||
<ClCompile Include="scripttask.cpp" />
|
<ClCompile Include="scripttask.cpp" />
|
||||||
<ClCompile Include="socket.cpp" />
|
<ClCompile Include="socket.cpp" />
|
||||||
|
<ClCompile Include="stacktrace.cpp" />
|
||||||
<ClCompile Include="stdiostream.cpp" />
|
<ClCompile Include="stdiostream.cpp" />
|
||||||
<ClCompile Include="stream.cpp" />
|
<ClCompile Include="stream.cpp" />
|
||||||
<ClCompile Include="streamlogger.cpp" />
|
<ClCompile Include="streamlogger.cpp" />
|
||||||
|
@ -62,6 +64,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="application.h" />
|
<ClInclude Include="application.h" />
|
||||||
<ClInclude Include="asynctask.h" />
|
<ClInclude Include="asynctask.h" />
|
||||||
|
<ClInclude Include="attribute.h" />
|
||||||
<ClInclude Include="component.h" />
|
<ClInclude Include="component.h" />
|
||||||
<ClInclude Include="connection.h" />
|
<ClInclude Include="connection.h" />
|
||||||
<ClInclude Include="convert.h" />
|
<ClInclude Include="convert.h" />
|
||||||
|
@ -70,6 +73,7 @@
|
||||||
<ClInclude Include="dynamictype.h" />
|
<ClInclude Include="dynamictype.h" />
|
||||||
<ClInclude Include="eventqueue.h" />
|
<ClInclude Include="eventqueue.h" />
|
||||||
<ClInclude Include="fifo.h" />
|
<ClInclude Include="fifo.h" />
|
||||||
|
<ClInclude Include="stacktrace.h" />
|
||||||
<ClInclude Include="stdiostream.h" />
|
<ClInclude Include="stdiostream.h" />
|
||||||
<ClInclude Include="stream.h" />
|
<ClInclude Include="stream.h" />
|
||||||
<ClInclude Include="netstring.h" />
|
<ClInclude Include="netstring.h" />
|
||||||
|
@ -177,7 +181,7 @@
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>dbghelp.lib;ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
||||||
|
@ -196,7 +200,7 @@
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Windows</SubSystem>
|
<SubSystem>Windows</SubSystem>
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>dbghelp.lib;ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MTd.lib;ssleay32MTd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
||||||
|
@ -220,7 +224,7 @@
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>dbghelp.lib;ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
||||||
|
@ -244,7 +248,7 @@
|
||||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
<OptimizeReferences>true</OptimizeReferences>
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
<AdditionalDependencies>dbghelp.lib;ws2_32.lib;shlwapi.lib;mmatch.lib;cJSON.lib;libeay32MT.lib;ssleay32MT.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||||
</Link>
|
</Link>
|
||||||
<Lib>
|
<Lib>
|
||||||
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
|
||||||
|
|
|
@ -103,6 +103,12 @@
|
||||||
<ClCompile Include="eventqueue.cpp">
|
<ClCompile Include="eventqueue.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="attribute.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="stacktrace.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="application.h">
|
<ClInclude Include="application.h">
|
||||||
|
@ -210,6 +216,12 @@
|
||||||
<ClInclude Include="eventqueue.h">
|
<ClInclude Include="eventqueue.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="attribute.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="stacktrace.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Quelldateien">
|
<Filter Include="Quelldateien">
|
||||||
|
|
|
@ -94,16 +94,20 @@ void EventQueue::QueueThreadProc(void)
|
||||||
|
|
||||||
BOOST_FOREACH(const Callback& ev, events) {
|
BOOST_FOREACH(const Callback& ev, events) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
|
double st = Utility::GetTime();
|
||||||
|
|
||||||
|
# ifdef RUSAGE_THREAD
|
||||||
struct rusage usage_start, usage_end;
|
struct rusage usage_start, usage_end;
|
||||||
|
|
||||||
double st = Utility::GetTime();
|
|
||||||
(void) getrusage(RUSAGE_THREAD, &usage_start);
|
(void) getrusage(RUSAGE_THREAD, &usage_start);
|
||||||
|
# endif /* RUSAGE_THREAD */
|
||||||
#endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
ev();
|
ev();
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
double et = Utility::GetTime();
|
double et = Utility::GetTime();
|
||||||
|
# ifdef RUSAGE_THREAD
|
||||||
(void) getrusage(RUSAGE_THREAD, &usage_end);
|
(void) getrusage(RUSAGE_THREAD, &usage_end);
|
||||||
|
|
||||||
double duser = (usage_end.ru_utime.tv_sec - usage_start.ru_utime.tv_sec) +
|
double duser = (usage_end.ru_utime.tv_sec - usage_start.ru_utime.tv_sec) +
|
||||||
|
@ -119,10 +123,15 @@ void EventQueue::QueueThreadProc(void)
|
||||||
|
|
||||||
int dvctx = usage_end.ru_nvcsw - usage_start.ru_nvcsw;
|
int dvctx = usage_end.ru_nvcsw - usage_start.ru_nvcsw;
|
||||||
int divctx = usage_end.ru_nivcsw - usage_start.ru_nivcsw;
|
int divctx = usage_end.ru_nivcsw - usage_start.ru_nivcsw;
|
||||||
|
# endif /* RUSAGE_THREAD */
|
||||||
if (et - st > 0.5) {
|
if (et - st > 0.5) {
|
||||||
stringstream msgbuf;
|
stringstream msgbuf;
|
||||||
|
# ifdef RUSAGE_THREAD
|
||||||
msgbuf << "Event call took user:" << duser << "s, system:" << dsys << "s, wait:" << dwait << "s, minor_faults:" << dminfaults << ", major_faults:" << dmajfaults << ", voluntary_csw:" << dvctx << ", involuntary_csw:" << divctx;
|
msgbuf << "Event call took user:" << duser << "s, system:" << dsys << "s, wait:" << dwait << "s, minor_faults:" << dminfaults << ", major_faults:" << dmajfaults << ", voluntary_csw:" << dvctx << ", involuntary_csw:" << divctx;
|
||||||
|
# else
|
||||||
|
msgbuf << "Event call took " << (et - st) << "s";
|
||||||
|
# endif /* RUSAGE_THREAD */
|
||||||
|
|
||||||
Logger::Write(LogWarning, "base", msgbuf.str());
|
Logger::Write(LogWarning, "base", msgbuf.str());
|
||||||
}
|
}
|
||||||
#endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
|
@ -77,6 +77,7 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
@ -191,6 +192,7 @@ namespace signals2 = boost::signals2;
|
||||||
|
|
||||||
#include "qstring.h"
|
#include "qstring.h"
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
|
#include "stacktrace.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "objectlock.h"
|
#include "objectlock.h"
|
||||||
#include "exception.h"
|
#include "exception.h"
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "i2-base.h"
|
||||||
|
#if HAVE_BACKTRACE_SYMBOLS
|
||||||
|
# include <execinfo.h>
|
||||||
|
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
|
||||||
|
using namespace icinga;
|
||||||
|
|
||||||
|
boost::once_flag StackTrace::m_OnceFlag = BOOST_ONCE_INIT;
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma optimize("", off)
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
StackTrace::StackTrace(void)
|
||||||
|
{
|
||||||
|
boost::call_once(m_OnceFlag, &StackTrace::Initialize);
|
||||||
|
|
||||||
|
#if HAVE_BACKTRACE_SYMBOLS
|
||||||
|
m_Count = backtrace(m_Frames, sizeof(m_Frames) / sizeof(m_Frames[0]));
|
||||||
|
#else /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
# ifdef _WIN32
|
||||||
|
m_Count = CaptureStackBackTrace(0, sizeof(m_Frames) / sizeof(m_Frames), m_Frames, NULL);
|
||||||
|
# else /* _WIN32 */
|
||||||
|
m_Count = 0;
|
||||||
|
# endif /* _WIN32 */
|
||||||
|
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
# pragma optimize("", on)
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
StackTrace::StackTrace(PEXCEPTION_POINTERS exi)
|
||||||
|
{
|
||||||
|
boost::call_once(m_OnceFlag, &StackTrace::Initialize);
|
||||||
|
|
||||||
|
STACKFRAME64 frame;
|
||||||
|
int architecture;
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
architecture = IMAGE_FILE_MACHINE_AMD64;
|
||||||
|
|
||||||
|
frame.AddrPC.Offset = exi->ContextRecord->Rip;
|
||||||
|
frame.AddrFrame.Offset = exi->ContextRecord->Rbp;
|
||||||
|
frame.AddrStack.Offset = exi->ContextRecord->Rsp;
|
||||||
|
#else /* _WIN64 */
|
||||||
|
architecture = IMAGE_FILE_MACHINE_I386;
|
||||||
|
|
||||||
|
frame.AddrPC.Offset = exi->ContextRecord->Eip;
|
||||||
|
frame.AddrFrame.Offset = exi->ContextRecord->Ebp;
|
||||||
|
frame.AddrStack.Offset = exi->ContextRecord->Esp;
|
||||||
|
#endif /* _WIN64 */
|
||||||
|
|
||||||
|
frame.AddrPC.Mode = AddrModeFlat;
|
||||||
|
frame.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
frame.AddrStack.Mode = AddrModeFlat;
|
||||||
|
|
||||||
|
m_Count = 0;
|
||||||
|
|
||||||
|
while (StackWalk64(architecture, GetCurrentProcess(), GetCurrentThread(),
|
||||||
|
&frame, exi->ContextRecord, NULL, &SymFunctionTableAccess64,
|
||||||
|
&SymGetModuleBase64, NULL) && m_Count < sizeof(m_Frames) / sizeof(m_Frames[0])) {
|
||||||
|
m_Frames[m_Count] = reinterpret_cast<void *>(frame.AddrPC.Offset);
|
||||||
|
m_Count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
void StackTrace::Initialize(void)
|
||||||
|
{
|
||||||
|
(void) SymSetOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES);
|
||||||
|
(void) SymInitialize(GetCurrentProcess(), NULL, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
void StackTrace::Print(ostream& fp, int ignoreFrames)
|
||||||
|
{
|
||||||
|
fp << std::endl << "Stacktrace:" << std::endl;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
# if HAVE_BACKTRACE_SYMBOLS
|
||||||
|
char **messages = backtrace_symbols(m_Frames, m_Count);
|
||||||
|
|
||||||
|
for (int i = ignoreFrames + 1; i < m_Count && 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 */
|
||||||
|
fp << "(not available)" << std::endl;
|
||||||
|
# endif /* HAVE_BACKTRACE_SYMBOLS */
|
||||||
|
#else /* _WIN32 */
|
||||||
|
for (int i = ignoreFrames + 1; i < m_Count; i++) {
|
||||||
|
char buffer[sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR)];
|
||||||
|
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
|
||||||
|
pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||||
|
pSymbol->MaxNameLen = MAX_SYM_NAME;
|
||||||
|
|
||||||
|
DWORD64 dwAddress = (DWORD64)m_Frames[i];
|
||||||
|
DWORD dwDisplacement;
|
||||||
|
DWORD64 dwDisplacement64;
|
||||||
|
|
||||||
|
IMAGEHLP_LINE64 line;
|
||||||
|
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
|
||||||
|
|
||||||
|
(void) SymGetLineFromAddr64(GetCurrentProcess(), dwAddress, &dwDisplacement, &line);
|
||||||
|
(void) SymFromAddr(GetCurrentProcess(), dwAddress, &dwDisplacement64, pSymbol);
|
||||||
|
|
||||||
|
fp << "\t(" << i - ignoreFrames - 1 << ") " << line.FileName << ":" << line.LineNumber << ": " << pSymbol->Name << "+" << dwDisplacement64 << std::endl;
|
||||||
|
}
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Icinga 2 *
|
||||||
|
* Copyright (C) 2012 Icinga Development Team (http://www.icinga.org/) *
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or *
|
||||||
|
* modify it under the terms of the GNU General Public License *
|
||||||
|
* as published by the Free Software Foundation; either version 2 *
|
||||||
|
* of the License, or (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
* This program is distributed in the hope that it will be useful, *
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||||
|
* GNU General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU General Public License *
|
||||||
|
* along with this program; if not, write to the Free Software Foundation *
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef STACKTRACE_H
|
||||||
|
#define STACKTRACE_H
|
||||||
|
|
||||||
|
namespace icinga
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stacktrace.
|
||||||
|
*
|
||||||
|
* @ingroup base
|
||||||
|
*/
|
||||||
|
class StackTrace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StackTrace(void);
|
||||||
|
#ifdef _WIN32
|
||||||
|
StackTrace(PEXCEPTION_POINTERS exi);
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
void Print(ostream& fp, int ignoreFrames = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void *m_Frames[64];
|
||||||
|
int m_Count;
|
||||||
|
|
||||||
|
static boost::once_flag m_OnceFlag;
|
||||||
|
|
||||||
|
static void Initialize(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* UTILITY_H */
|
|
@ -30,7 +30,6 @@
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
|
|
|
@ -19,9 +19,6 @@
|
||||||
|
|
||||||
#include "i2-base.h"
|
#include "i2-base.h"
|
||||||
#include <mmatch.h>
|
#include <mmatch.h>
|
||||||
#if HAVE_BACKTRACE_SYMBOLS
|
|
||||||
# include <execinfo.h>
|
|
||||||
#endif /* HAVE_BACKTRACE_SYMBOLS */
|
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
@ -61,55 +58,7 @@ 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)
|
|
||||||
{
|
|
||||||
#if 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,7 +33,6 @@ 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);
|
||||||
|
|
||||||
|
|
|
@ -508,8 +508,6 @@ set<Service::Ptr> Host::GetParentServices(void) const
|
||||||
|
|
||||||
HostState Host::GetState(void) const
|
HostState Host::GetState(void) const
|
||||||
{
|
{
|
||||||
assert(!OwnsLock());
|
|
||||||
|
|
||||||
if (!IsReachable())
|
if (!IsReachable())
|
||||||
return HostUnreachable;
|
return HostUnreachable;
|
||||||
|
|
||||||
|
@ -594,18 +592,6 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
|
||||||
macros->Set("HOSTNAME", GetName());
|
macros->Set("HOSTNAME", GetName());
|
||||||
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
|
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
|
||||||
macros->Set("HOSTALIAS", GetName());
|
macros->Set("HOSTALIAS", GetName());
|
||||||
|
|
||||||
HostState state = GetState();
|
|
||||||
|
|
||||||
macros->Set("HOSTSTATE", HostStateToString(GetState()));
|
|
||||||
macros->Set("HOSTSTATEID", GetState());
|
|
||||||
|
|
||||||
HostState lastState = GetLastState();
|
|
||||||
StateType lastStateType = GetLastStateType();
|
|
||||||
|
|
||||||
macros->Set("LASTHOSTSTATE", HostStateToString(lastState));
|
|
||||||
macros->Set("LASTHOSTSTATEID", lastState);
|
|
||||||
macros->Set("LASTHOSTSTATETYPE", Service::StateTypeToString(lastStateType));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::Ptr cr;
|
Dictionary::Ptr cr;
|
||||||
|
@ -615,11 +601,16 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
|
||||||
if (hc) {
|
if (hc) {
|
||||||
ObjectLock olock(hc);
|
ObjectLock olock(hc);
|
||||||
|
|
||||||
|
macros->Set("HOSTSTATE", HostStateToString(GetState()));
|
||||||
|
macros->Set("HOSTSTATEID", GetState());
|
||||||
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hc->GetStateType()));
|
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hc->GetStateType()));
|
||||||
macros->Set("HOSTATTEMPT", hc->GetCurrentCheckAttempt());
|
macros->Set("HOSTATTEMPT", hc->GetCurrentCheckAttempt());
|
||||||
macros->Set("MAXHOSTATTEMPT", hc->GetMaxCheckAttempts());
|
macros->Set("MAXHOSTATTEMPT", hc->GetMaxCheckAttempts());
|
||||||
|
|
||||||
macros->Set("LASTHOSTSTATECHANGE", (time_t)hc->GetLastStateChange());
|
macros->Set("LASTHOSTSTATE", HostStateToString(GetLastState()));
|
||||||
|
macros->Set("LASTHOSTSTATEID", GetLastState());
|
||||||
|
macros->Set("LASTHOSTSTATETYPE", Service::StateTypeToString(GetLastStateType()));
|
||||||
|
macros->Set("LASTHOSTSTATECHANGE", (long)hc->GetLastStateChange());
|
||||||
|
|
||||||
cr = hc->GetLastCheckResult();
|
cr = hc->GetLastCheckResult();
|
||||||
}
|
}
|
||||||
|
@ -631,7 +622,7 @@ Dictionary::Ptr Host::CalculateDynamicMacros(void) const
|
||||||
macros->Set("HOSTOUTPUT", cr->Get("output"));
|
macros->Set("HOSTOUTPUT", cr->Get("output"));
|
||||||
macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw"));
|
macros->Set("HOSTPERFDATA", cr->Get("performance_data_raw"));
|
||||||
|
|
||||||
macros->Set("LASTHOSTCHECK", (time_t)cr->Get("schedule_start"));
|
macros->Set("LASTHOSTCHECK", (long)cr->Get("schedule_start"));
|
||||||
}
|
}
|
||||||
|
|
||||||
macros->Seal();
|
macros->Seal();
|
||||||
|
|
|
@ -58,6 +58,15 @@
|
||||||
<ClCompile Include="service-notification.cpp">
|
<ClCompile Include="service-notification.cpp">
|
||||||
<Filter>Quelldateien</Filter>
|
<Filter>Quelldateien</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="api.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="user.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="usergroup.cpp">
|
||||||
|
<Filter>Quelldateien</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="i2-icinga.h">
|
<ClInclude Include="i2-icinga.h">
|
||||||
|
@ -105,6 +114,15 @@
|
||||||
<ClInclude Include="notificationrequestmessage.h">
|
<ClInclude Include="notificationrequestmessage.h">
|
||||||
<Filter>Headerdateien</Filter>
|
<Filter>Headerdateien</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="api.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="user.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="usergroup.h">
|
||||||
|
<Filter>Headerdateien</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Filter Include="Headerdateien">
|
<Filter Include="Headerdateien">
|
||||||
|
|
|
@ -74,7 +74,7 @@ int IcingaApplication::Main(void)
|
||||||
|
|
||||||
/* periodically dump the program state */
|
/* periodically dump the program state */
|
||||||
m_RetentionTimer = boost::make_shared<Timer>();
|
m_RetentionTimer = boost::make_shared<Timer>();
|
||||||
m_RetentionTimer->SetInterval(300);
|
m_RetentionTimer->SetInterval(3);
|
||||||
m_RetentionTimer->OnTimerExpired.connect(boost::bind(&IcingaApplication::DumpProgramState, this));
|
m_RetentionTimer->OnTimerExpired.connect(boost::bind(&IcingaApplication::DumpProgramState, this));
|
||||||
m_RetentionTimer->Start();
|
m_RetentionTimer->Start();
|
||||||
|
|
||||||
|
|
|
@ -416,8 +416,6 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
|
||||||
int state = cr->Get("state");
|
int state = cr->Get("state");
|
||||||
SetState(static_cast<ServiceState>(state));
|
SetState(static_cast<ServiceState>(state));
|
||||||
|
|
||||||
SetLastCheckResult(cr);
|
|
||||||
|
|
||||||
double now = Utility::GetTime();
|
double now = Utility::GetTime();
|
||||||
|
|
||||||
if (old_state != GetState()) {
|
if (old_state != GetState()) {
|
||||||
|
@ -459,13 +457,19 @@ void Service::ProcessCheckResult(const Dictionary::Ptr& cr)
|
||||||
|
|
||||||
olock.Unlock();
|
olock.Unlock();
|
||||||
|
|
||||||
|
/* Update macros - these are used by event handlers and notifications. */
|
||||||
|
cr->Set("macros", CalculateAllMacros());
|
||||||
|
|
||||||
|
cr->Seal();
|
||||||
|
|
||||||
|
olock.Lock();
|
||||||
|
SetLastCheckResult(cr);
|
||||||
|
olock.Unlock();
|
||||||
|
|
||||||
/* Flush the object so other instances see the service's
|
/* Flush the object so other instances see the service's
|
||||||
* new state when they receive the CheckResult message */
|
* new state when they receive the CheckResult message */
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
/* Update macros - these are used by event handlers and notifications. */
|
|
||||||
cr->Set("macros", CalculateAllMacros());
|
|
||||||
|
|
||||||
RequestMessage rm;
|
RequestMessage rm;
|
||||||
rm.SetMethod("checker::CheckResult");
|
rm.SetMethod("checker::CheckResult");
|
||||||
|
|
||||||
|
@ -664,8 +668,6 @@ void Service::CheckCompletedHandler(const Dictionary::Ptr& checkInfo,
|
||||||
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
EndpointManager::Ptr em = EndpointManager::GetInstance();
|
||||||
result->Set("current_checker", em->GetIdentity());
|
result->Set("current_checker", em->GetIdentity());
|
||||||
}
|
}
|
||||||
|
|
||||||
result->Seal();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
|
|
|
@ -448,7 +448,7 @@ Dictionary::Ptr Service::CalculateDynamicMacros(void) const
|
||||||
macros->Set("LASTSERVICESTATE", StateToString(GetLastState()));
|
macros->Set("LASTSERVICESTATE", StateToString(GetLastState()));
|
||||||
macros->Set("LASTSERVICESTATEID", GetLastState());
|
macros->Set("LASTSERVICESTATEID", GetLastState());
|
||||||
macros->Set("LASTSERVICESTATETYPE", StateTypeToString(GetLastStateType()));
|
macros->Set("LASTSERVICESTATETYPE", StateTypeToString(GetLastStateType()));
|
||||||
macros->Set("LASTSERVICESTATECHANGE", (time_t)GetLastStateChange());
|
macros->Set("LASTSERVICESTATECHANGE", (long)GetLastStateChange());
|
||||||
|
|
||||||
cr = GetLastCheckResult();
|
cr = GetLastCheckResult();
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ Dictionary::Ptr Service::CalculateDynamicMacros(void) const
|
||||||
macros->Set("SERVICEOUTPUT", cr->Get("output"));
|
macros->Set("SERVICEOUTPUT", cr->Get("output"));
|
||||||
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
|
macros->Set("SERVICEPERFDATA", cr->Get("performance_data_raw"));
|
||||||
|
|
||||||
macros->Set("LASTSERVICECHECK", (time_t)cr->Get("schedule_start"));
|
macros->Set("LASTSERVICECHECK", (long)cr->Get("schedule_start"));
|
||||||
}
|
}
|
||||||
|
|
||||||
macros->Seal();
|
macros->Seal();
|
||||||
|
|
Loading…
Reference in New Issue