scripttask.h \
socket.cpp \
socket.h \
+ stacktrace.cpp \
+ stacktrace.h \
stdiostream.cpp \
stdiostream.h \
stream.cpp \
{
assert(signum == SIGABRT);
+#ifndef _WIN32
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGABRT, &sa, NULL);
+#endif /* _WIN32 */
std::cerr << "Caught SIGABRT." << std::endl;
<< std::endl;
}
- Utility::PrintStacktrace(std::cerr, 1);
+ StackTrace trace;
+ trace.Print(std::cerr, 1);
DisplayBugMessage();
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.
memset(&sa, 0, sizeof(sa));
sa.sa_handler = &Application::SigAbrtHandler;
sigaction(SIGABRT, &sa, NULL);
+#else /* _WIN32 */
+ SetUnhandledExceptionFilter(&Application::SEHUnhandledExceptionFilter);
#endif /* _WIN32 */
}
#ifndef _WIN32
static void SigIntHandler(int signum);
- static void SigAbrtHandler(int signum);
#else /* _WIN32 */
static BOOL WINAPI CtrlHandler(DWORD type);
+ static LONG WINAPI SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi);
#endif /* _WIN32 */
static void DisplayBugMessage(void);
+ static void SigAbrtHandler(int signum);
static void ExceptionHandler(void);
static void TimeWatchThreadProc(void);
</ItemGroup>
<ItemGroup>
<ClCompile Include="application.cpp" />
+ <ClCompile Include="attribute.cpp" />
<ClCompile Include="component.cpp" />
<ClCompile Include="connection.cpp" />
<ClCompile Include="convert.cpp" />
<ClCompile Include="scriptfunction.cpp" />
<ClCompile Include="scripttask.cpp" />
<ClCompile Include="socket.cpp" />
+ <ClCompile Include="stacktrace.cpp" />
<ClCompile Include="stdiostream.cpp" />
<ClCompile Include="stream.cpp" />
<ClCompile Include="streamlogger.cpp" />
<ItemGroup>
<ClInclude Include="application.h" />
<ClInclude Include="asynctask.h" />
+ <ClInclude Include="attribute.h" />
<ClInclude Include="component.h" />
<ClInclude Include="connection.h" />
<ClInclude Include="convert.h" />
<ClInclude Include="dynamictype.h" />
<ClInclude Include="eventqueue.h" />
<ClInclude Include="fifo.h" />
+ <ClInclude Include="stacktrace.h" />
<ClInclude Include="stdiostream.h" />
<ClInclude Include="stream.h" />
<ClInclude Include="netstring.h" />
<Link>
<SubSystem>Windows</SubSystem>
<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>
<Lib>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
<Link>
<SubSystem>Windows</SubSystem>
<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>
<Lib>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<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>
<Lib>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<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>
<Lib>
<AdditionalDependencies>ws2_32.lib;shlwapi.lib</AdditionalDependencies>
<ClCompile Include="eventqueue.cpp">
<Filter>Quelldateien</Filter>
</ClCompile>
+ <ClCompile Include="attribute.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
+ <ClCompile Include="stacktrace.cpp">
+ <Filter>Quelldateien</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="application.h">
<ClInclude Include="eventqueue.h">
<Filter>Headerdateien</Filter>
</ClInclude>
+ <ClInclude Include="attribute.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
+ <ClInclude Include="stacktrace.h">
+ <Filter>Headerdateien</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Quelldateien">
BOOST_FOREACH(const Callback& ev, events) {
#ifdef _DEBUG
+ double st = Utility::GetTime();
+
+# ifdef RUSAGE_THREAD
struct rusage usage_start, usage_end;
- double st = Utility::GetTime();
(void) getrusage(RUSAGE_THREAD, &usage_start);
+# endif /* RUSAGE_THREAD */
#endif /* _DEBUG */
ev();
#ifdef _DEBUG
double et = Utility::GetTime();
+# ifdef RUSAGE_THREAD
(void) getrusage(RUSAGE_THREAD, &usage_end);
double duser = (usage_end.ru_utime.tv_sec - usage_start.ru_utime.tv_sec) +
int dvctx = usage_end.ru_nvcsw - usage_start.ru_nvcsw;
int divctx = usage_end.ru_nivcsw - usage_start.ru_nivcsw;
-
+# endif /* RUSAGE_THREAD */
if (et - st > 0.5) {
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;
+# else
+ msgbuf << "Event call took " << (et - st) << "s";
+# endif /* RUSAGE_THREAD */
+
Logger::Write(LogWarning, "base", msgbuf.str());
}
#endif /* _DEBUG */
#include <sys/types.h>
#include <sys/stat.h>
+#include <signal.h>
#include <string>
#include <exception>
#include "qstring.h"
#include "utility.h"
+#include "stacktrace.h"
#include "object.h"
#include "objectlock.h"
#include "exception.h"
--- /dev/null
+/******************************************************************************
+ * 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 */
+}
--- /dev/null
+/******************************************************************************
+ * 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 */
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
-#include <signal.h>
#include <libgen.h>
#include <syslog.h>
#include <sys/file.h>
#include "i2-base.h"
#include <mmatch.h>
-#if HAVE_BACKTRACE_SYMBOLS
-# include <execinfo.h>
-#endif /* HAVE_BACKTRACE_SYMBOLS */
using namespace icinga;
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.
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);
HostState Host::GetState(void) const
{
- assert(!OwnsLock());
-
if (!IsReachable())
return HostUnreachable;
macros->Set("HOSTNAME", GetName());
macros->Set("HOSTDISPLAYNAME", GetDisplayName());
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;
if (hc) {
ObjectLock olock(hc);
+ macros->Set("HOSTSTATE", HostStateToString(GetState()));
+ macros->Set("HOSTSTATEID", GetState());
macros->Set("HOSTSTATETYPE", Service::StateTypeToString(hc->GetStateType()));
macros->Set("HOSTATTEMPT", hc->GetCurrentCheckAttempt());
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();
}
macros->Set("HOSTOUTPUT", cr->Get("output"));
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();
<ClCompile Include="service-notification.cpp">
<Filter>Quelldateien</Filter>
</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>
<ClInclude Include="i2-icinga.h">
<ClInclude Include="notificationrequestmessage.h">
<Filter>Headerdateien</Filter>
</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>
<Filter Include="Headerdateien">
/* periodically dump the program state */
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->Start();
int state = cr->Get("state");
SetState(static_cast<ServiceState>(state));
- SetLastCheckResult(cr);
-
double now = Utility::GetTime();
if (old_state != GetState()) {
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
* new state when they receive the CheckResult message */
Flush();
- /* Update macros - these are used by event handlers and notifications. */
- cr->Set("macros", CalculateAllMacros());
-
RequestMessage rm;
rm.SetMethod("checker::CheckResult");
EndpointManager::Ptr em = EndpointManager::GetInstance();
result->Set("current_checker", em->GetIdentity());
}
-
- result->Seal();
}
if (result)
macros->Set("LASTSERVICESTATE", StateToString(GetLastState()));
macros->Set("LASTSERVICESTATEID", GetLastState());
macros->Set("LASTSERVICESTATETYPE", StateTypeToString(GetLastStateType()));
- macros->Set("LASTSERVICESTATECHANGE", (time_t)GetLastStateChange());
+ macros->Set("LASTSERVICESTATECHANGE", (long)GetLastStateChange());
cr = GetLastCheckResult();
}
macros->Set("SERVICEOUTPUT", cr->Get("output"));
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();