mirror of https://github.com/Icinga/icinga2.git
Run termination handler for uncaught C++ exceptions on Windows
On Windows, the termination handler is executed for uncaught C++ exceptions unless a SEH unhandled exception filter is also set. In this case, this filter has to explicitly chain the default filter to keep this behavior.
This commit is contained in:
parent
0b26515c34
commit
f8b7a1511b
|
@ -34,6 +34,14 @@
|
||||||
|
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
/* MSVC throws unhandled C++ exceptions as SEH exceptions with this specific error code.
|
||||||
|
* There seems to be no system header that actually defines this constant.
|
||||||
|
* See also https://devblogs.microsoft.com/oldnewthing/20160915-00/?p=94316
|
||||||
|
*/
|
||||||
|
#define EXCEPTION_CODE_CXX_EXCEPTION 0xe06d7363
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
REGISTER_TYPE(Application);
|
REGISTER_TYPE(Application);
|
||||||
|
|
||||||
boost::signals2::signal<void ()> Application::OnReopenLogs;
|
boost::signals2::signal<void ()> Application::OnReopenLogs;
|
||||||
|
@ -55,6 +63,10 @@ double Application::m_StartTime;
|
||||||
bool Application::m_ScriptDebuggerEnabled = false;
|
bool Application::m_ScriptDebuggerEnabled = false;
|
||||||
double Application::m_LastReloadFailed;
|
double Application::m_LastReloadFailed;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
static LPTOP_LEVEL_EXCEPTION_FILTER l_DefaultUnhandledExceptionFilter = nullptr;
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor for the Application class.
|
* Constructor for the Application class.
|
||||||
*/
|
*/
|
||||||
|
@ -885,6 +897,15 @@ void Application::ExceptionHandler()
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
|
LONG CALLBACK Application::SEHUnhandledExceptionFilter(PEXCEPTION_POINTERS exi)
|
||||||
{
|
{
|
||||||
|
/* If an unhandled C++ exception occurs with both a termination handler (std::set_terminate()) and an unhandled
|
||||||
|
* SEH filter (SetUnhandledExceptionFilter()) set, the latter one is called. However, our termination handler is
|
||||||
|
* better suited for dealing with C++ exceptions. In this case, the SEH exception will have a specific code and
|
||||||
|
* we can just call the default filter function which will take care of calling the termination handler.
|
||||||
|
*/
|
||||||
|
if (exi->ExceptionRecord->ExceptionCode == EXCEPTION_CODE_CXX_EXCEPTION) {
|
||||||
|
return l_DefaultUnhandledExceptionFilter(exi);
|
||||||
|
}
|
||||||
|
|
||||||
if (l_InExceptionHandler)
|
if (l_InExceptionHandler)
|
||||||
return EXCEPTION_CONTINUE_SEARCH;
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
|
||||||
|
@ -938,7 +959,7 @@ void Application::InstallExceptionHandlers()
|
||||||
sa.sa_handler = &Application::SigAbrtHandler;
|
sa.sa_handler = &Application::SigAbrtHandler;
|
||||||
sigaction(SIGABRT, &sa, nullptr);
|
sigaction(SIGABRT, &sa, nullptr);
|
||||||
#else /* _WIN32 */
|
#else /* _WIN32 */
|
||||||
SetUnhandledExceptionFilter(&Application::SEHUnhandledExceptionFilter);
|
l_DefaultUnhandledExceptionFilter = SetUnhandledExceptionFilter(&Application::SEHUnhandledExceptionFilter);
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue