mirror of
https://github.com/KjellKod/g3log.git
synced 2025-01-31 14:39:54 +01:00
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:
parent
9e3ed03310
commit
81885e4456
@ -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)
|
||||
|
@ -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)
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user