Enabled vectored exception crash handling, it can also be turned off easily with a define

cmake -DENABLE_VECTORED_EXCEPTIONHANDLING=OFF
This commit is contained in:
Kjell Hedstrom 2015-02-16 01:37:55 -07:00
parent 9e3ed03310
commit 81885e4456
6 changed files with 74 additions and 33 deletions

View File

@ -31,7 +31,7 @@ ELSEIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
ELSEIF(MSVC)
ELSEIF (MSVC OR MINGW)
set(PLATFORM_LINK_LIBRIES dbghelp)
# VC11 bug: http://code.google.com/p/googletest/issues/detail?id=408
# add_definition(-D_VARIADIC_MAX=10)

View File

@ -1,13 +1,10 @@
# -DUSE_DYNAMIC_LOGGING_LEVELS=ON : run-type turn on/off levels
option (USE_DYNAMIC_LOGGING_LEVELS
"Turn ON/OFF log levels. An disabled level will not push logs of that level to the sink. By default dynamic logging is disabled" OFF)
IF(USE_DYNAMIC_LOGGING_LEVELS)
add_definitions(-DG2_DYNAMIC_LOGGING)
MESSAGE("-DUSE_DYNAMIC_LOGGING_LEVELS=ON
\tDynamic logging levels can be turned on. Make sure to have \n\t\t[#define G2_DYNAMIC_LOGGING 1] in your source code")
MESSAGE("-DUSE_DYNAMIC_LOGGING_LEVELS=ON")
MESSAGE("\tDynamic logging levels can be turned on. Make sure to have \n\t\t[#define G2_DYNAMIC_LOGGING 1] in your source code")
MESSAGE("\t\tUse [g2::setLogLevel(LEVEL boolean)] to enable/disable logging on specified levels")
ELSE()
MESSAGE("-DUSE_DYNAMIC_LOGGING_LEVELS=OFF")
@ -20,13 +17,32 @@ ENDIF(USE_DYNAMIC_LOGGING_LEVELS)
# predefined DEBUG for their own purposes
option (CHANGE_G3LOG_DEBUG_TO_DBUG
"Use DBUG logging level instead of DEBUG. By default DEBUG is the debugging level" OFF)
IF(CHANGE_G3LOG_DEBUG_TO_DBUG)
add_definitions(-DCHANGE_G3LOG_DEBUG_TO_DBUG)
MESSAGE("-DCHANGE_G3LOG_DEBUG_TO_DBUG=ON
\tDBUG instead of DEBUG logging level can be used. Make sure to have \n\t\t[#define CHANGE_G3LOG_DEBUG_TO_DBUG 1] in your source code")
MESSAGE("-DCHANGE_G3LOG_DEBUG_TO_DBUG=ON")
MESSAGE("\tDBUG instead of DEBUG logging level can be used. Make sure to have \n\t\t[#define CHANGE_G3LOG_DEBUG_TO_DBUG 1] in your source code")
ELSE()
MESSAGE("-DCHANGE_G3LOG_DEBUG_TO_DBUG=OFF. Debuggin logging level is 'DEBUG'")
MESSAGE("-DCHANGE_G3LOG_DEBUG_TO_DBUG=OFF")
MESSAGE("\tDebuggin logging level is 'DEBUG'")
ENDIF(CHANGE_G3LOG_DEBUG_TO_DBUG)
# WINDOWS OPTION
# -DENABLE_VECTORED_EXCEPTIONHANDLING=ON : defualt change the
# By default vectored exception handling is enabled, you can disable it with this option.
# Please know that only known fatal exceptions will be caught, these exceptions are the ones
# enumerated in src/stacktrace_windows.cpp
IF (MSVC OR MINGW)
option (ENABLE_VECTORED_EXCEPTIONHANDLING
"Vectored exception / crash handling with improved stack trace" ON)
IF(NOT ENABLE_VECTORED_EXCEPTIONHANDLING)
add_definitions(-DDISABLE_VECTORED_EXCEPTIONHANDLING)
MESSAGE("-DENABLE_VECTORED_EXCEPTIONHANDLING=OFF")
MESSAGE("\tVectored exception handling is disabled")
ELSE()
MESSAGE("-DENABLE_VECTORED_EXCEPTIONHANDLING=ON")
MESSAGE("\tVectored exception handling is enabled")
ENDIF(NOT ENABLE_VECTORED_EXCEPTIONHANDLING)
ENDIF (MSVC OR MINGW)

View File

@ -136,6 +136,7 @@ void ExecuteDeathFunction(const bool runInNewThread, int fatalChoice) {
case 8: exitFunction = &OutOfBoundsArrayIndexing; break;
case 9: exitFunction = &AccessViolation; break;
case 10: exitFunction = &RaiseSIGABRTAndAccessViolation; break;
case 11: throw 123456789; break;
default: break;
}
if (runInNewThread) {
@ -191,12 +192,14 @@ int ChoiceOfFatalExit() {
std::cout << "[8] Out of bounds array indexing " << std::endl;
std::cout << "[9] Access violation" << std::endl;
std::cout << "[10] Rasing SIGABRT + Access Violation in two separate threads" << std::endl;
std::cout << "[11] Just throw" << std::endl;
std::cout << std::flush;
try {
std::getline(std::cin, option);
choice = std::stoi(option);
if (choice <= 0 || choice > 10) {
if (choice <= 0 || choice > 11) {
std::cout << "Invalid choice: [" << option << "\n\n";
} else {
return choice;

View File

@ -24,20 +24,24 @@
#include "g2logmessage.hpp"
#include "g2logmessagecapture.hpp"
namespace {
std::atomic<bool> gBlockForFatal {true};
//void* g_vector_exception_handler = nullptr;
LPTOP_LEVEL_EXCEPTION_FILTER g_previous_unexpected_exception_handler = nullptr;
g2_thread_local bool g_installed_thread_signal_handler = false;
#if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING))
void* g_vector_exception_handler = nullptr;
#endif
// Restore back to default fatal event handling
void ReverseToOriginalFatalHandling() {
SetUnhandledExceptionFilter (g_previous_unexpected_exception_handler);
//RemoveVectoredExceptionHandler (g_vector_exception_handler);
#if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING))
RemoveVectoredExceptionHandler (g_vector_exception_handler);
#endif
if (SIG_ERR == signal(SIGABRT, SIG_DFL))
perror("signal - SIGABRT");
@ -73,37 +77,41 @@ void signalHandler(int signal_number) {
// Unhandled exception catching
LONG WINAPI exceptionHandling(EXCEPTION_POINTERS* info) {
LONG WINAPI exceptionHandling(EXCEPTION_POINTERS* info, const std::string& handler) {
std::string dump = stacktrace::stackdump(info);
std::ostringstream fatal_stream;
const g2::SignalType exception_code = info->ExceptionRecord->ExceptionCode;
fatal_stream << "\n***** Received fatal exception " << g2::internal::exitReasonName(g2::internal::FATAL_EXCEPTION, exception_code);
fatal_stream << "\n***** " << handler << ": Received fatal exception " << g2::internal::exitReasonName(g2::internal::FATAL_EXCEPTION, exception_code);
fatal_stream << "\tPID: " << getpid() << std::endl;
const auto fatal_id = static_cast<g2::SignalType>(exception_code);
LogCapture trigger(g2::internal::FATAL_EXCEPTION, fatal_id, dump.c_str());
trigger.stream() << fatal_stream.str();
return EXCEPTION_CONTINUE_SEARCH; //EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_EXECUTE_HANDLER; // FATAL Exception: It stops here
}
// Unhandled exception catching
LONG WINAPI unexpectedExceptionHandling(EXCEPTION_POINTERS* info) {
ReverseToOriginalFatalHandling();
return exceptionHandling(info);
return exceptionHandling(info, "Unexpected Exception Handler");
}
/// Setup through (Windows API) AddVectoredExceptionHandler
/// Ref: http://blogs.msdn.com/b/zhanli/archive/2010/06/25/c-tips-addvectoredexceptionhandler-addvectoredcontinuehandler-and-setunhandledexceptionfilter.aspx
#if 0
LONG WINAPI vectorExceptionHandling(PEXCEPTION_POINTERS p) {
ReverseToOriginalFatalHandling();
return exceptionHandling(p);
}
#if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING))
LONG WINAPI vectorExceptionHandling(PEXCEPTION_POINTERS p) {
const g2::SignalType exception_code = p->ExceptionRecord->ExceptionCode;
if (false == stacktrace::isKnownException(exception_code)) {
LOG(WARNING) << "Vectored exception handling received an UNKNOWN exception: " << exception_code << ". The exception is IGNORED and hopefully caught by another exception handler";
return EXCEPTION_CONTINUE_SEARCH;
} else {
ReverseToOriginalFatalHandling();
return exceptionHandling(p, "Vectored Exception Handler");
}
}
#endif
@ -124,7 +132,7 @@ bool blockForFatalHandling() {
/// Generate stackdump. Or in case a stackdump was pre-generated and
/// non-empty just use that one. i.e. the latter case is only for
/// non-empty just use that one. i.e. the latter case is only for
/// Windows and test purposes
std::string stackdump(const char* dump) {
if (nullptr != dump && !std::string(dump).empty()) {
@ -209,10 +217,15 @@ void installSignalHandlerForThread() {
void installCrashHandler() {
internal::installSignalHandler();
//const size_t kFirstExceptionHandler = 1; // Kept here for documentational purposes. last exception seems more what we want
const size_t kLastExceptionHandler = 0;
//g_vector_exception_handler = AddVectoredExceptionHandler(kLastExceptionHandler, vectorExceptionHandling);
g_previous_unexpected_exception_handler = SetUnhandledExceptionFilter(unexpectedExceptionHandling);
#if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING))
// const size_t kFirstExceptionHandler = 1;
// kFirstExeptionsHandler is kept here for documentational purposes.
// The last exception seems more what we want
const size_t kLastExceptionHandler = 0;
g_vector_exception_handler = AddVectoredExceptionHandler(kLastExceptionHandler, vectorExceptionHandling);
#endif
}
} // end namespace g2

View File

@ -146,19 +146,24 @@ std::string convertFramesToText(std::vector<uint64_t>& frame_pointers) {
namespace stacktrace {
const std::string kUnknown = {"UNKNOWN EXCEPTION"};
/// return the text description of a Windows exception code
/// From MSDN GetExceptionCode http://msdn.microsoft.com/en-us/library/windows/desktop/ms679356(v=vs.85).aspx
std::string exceptionIdToText(g2::SignalType id) {
const auto iter = kExceptionsAsText.find(id);
if ( iter == kExceptionsAsText.end()) {
std::string unknown {"Unknown/" + std::to_string(id)};
std::string unknown = {kUnknown + ":" + std::to_string(id)};
return unknown;
}
return iter->second;
}
/// Yes a double lookup: first for isKnownException and then exceptionIdToText
/// for vectored exceptions we only deal with known exceptions so this tiny
/// overhead we can live with
bool isKnownException(g2::SignalType id) {
return (kExceptionsAsText.end() != kExceptionsAsText.find(id));
}
/// helper function: retrieve stackdump from no excisting exception pointer
std::string stackdump() {

View File

@ -27,6 +27,10 @@ namespace stacktrace {
/// return the text description of a Windows exception code
std::string exceptionIdToText(g2::SignalType id);
/// return whether or not the exception is a known exception, i.e.
/// an exception that we should treat as a fatal event
bool isKnownException(g2::SignalType id);
/// helper function: retrieve stackdump from no excisting exception pointer
std::string stackdump();