Merge pull request #7 from KjellKod/windows-vector-exceptions

Windows vector exceptions
This commit is contained in:
Kjell Hedstrom 2015-03-02 02:14:50 -07:00
commit 65846fdeaa
6 changed files with 56 additions and 12 deletions

View File

@ -233,10 +233,18 @@ void ChooseFatalExit() {
}
} // namespace
void breakHere() {
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
__debugbreak();
#endif
}
int main(int argc, char** argv)
{
auto logger_n_handle = g2::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
g2::initializeLogging(logger_n_handle.worker.get());
g2::setFatalPreLoggingHook(&breakHere);
std::future<std::string> log_file_name = logger_n_handle.sink->call(&g2::FileSink::fileName);
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
<< "Choose your type of fatal exit, then "

View File

@ -30,7 +30,7 @@ std::atomic<bool> gBlockForFatal {true};
LPTOP_LEVEL_EXCEPTION_FILTER g_previous_unexpected_exception_handler = nullptr;
#if !(defined(DISABLE_FATAL_SIGNALHANDLING))
g2_thread_local bool g_installed_thread_signal_handler = false;
thread_local bool g_installed_thread_signal_handler = false;
#endif
#if !(defined(DISABLE_VECTORED_EXCEPTIONHANDLING))

View File

@ -24,6 +24,8 @@
#include <csignal>
#include <memory>
#include <iostream>
#include <thread>
#include <atomic>
#include "std2_make_unique.hpp"
#include "g2logworker.hpp"
@ -41,6 +43,8 @@ std::once_flag g_save_first_unintialized_flag;
const std::function<void(void)> g_pre_fatal_hook_that_does_nothing = []{ /*does nothing */};
std::function<void(void)> g_fatal_pre_logging_hook;
std::atomic<size_t> g_fatal_hook_recursive_counter = {0};
}
@ -72,6 +76,8 @@ void initializeLogging(LogWorker* bgworker) {
// by default the pre fatal logging hook does nothing
// if it WOULD do something it would happen in
setFatalPreLoggingHook(g_pre_fatal_hook_that_does_nothing);
// recurvise crash counter re-set to zero
g_fatal_hook_recursive_counter.store(0);
}
@ -82,6 +88,8 @@ void initializeLogging(LogWorker* bgworker) {
* so please call this function, if you ever need to, after initializeLogging(...)
*/
void setFatalPreLoggingHook(std::function<void(void)> pre_fatal_hook) {
static std::mutex m;
std::lock_guard<std::mutex> lock(m);
g_fatal_pre_logging_hook = pre_fatal_hook;
}
@ -138,6 +146,7 @@ bool shutDownLoggingForActiveOnly(LogWorker* active) {
/** explicits copy of all input. This is makes it possibly to use g3log across dynamically loaded libraries
* i.e. (dlopen + dlsym) */
void saveMessage(const char* entry, const char* file, int line, const char* function, const LEVELS& level,
@ -147,11 +156,27 @@ void saveMessage(const char* entry, const char* file, int line, const char* func
message.get()->write().append(entry);
message.get()->setExpression(boolean_expression);
if (internal::wasFatal(level)) {
message.get()->write().append(stack_trace);
FatalMessagePtr fatal_message {std2::make_unique<FatalMessage>(*(message._move_only.get()), fatal_signal)};
g_fatal_pre_logging_hook(); // pre-fatal hook
if (internal::wasFatal(level)) {
auto fatalhook = g_fatal_pre_logging_hook;
// In case the fatal_pre logging actually will cause a crash in its turn
// let's not do recursive crashing!
setFatalPreLoggingHook(g_pre_fatal_hook_that_does_nothing);
++g_fatal_hook_recursive_counter; // thread safe counter
// "benign" race here. If two threads crashes, with recursive crashes
// then it's possible that the "other" fatal stack trace will be shown
// that's OK since it was anyhow the first crash detected
static const std::string first_stack_trace = stack_trace;
fatalhook();
message.get()->write().append(stack_trace);
if (g_fatal_hook_recursive_counter.load() > 1) {
message.get()->write()
.append("\n\n\nWARNING\n"
"A recursive crash detected. It is likely the hook set with 'setFatalPreLoggingHook(...)' is responsible\n\n")
.append("---First crash stacktrace: ").append(first_stack_trace).append("\n---End of first stacktrace\n");
}
FatalMessagePtr fatal_message{ std2::make_unique<FatalMessage>(*(message._move_only.get()), fatal_signal) };
// At destruction, flushes fatal message to g2LogWorker
// either we will stay here until the background worker has received the fatal
// message, flushed the crash message to the sinks and exits with the same fatal signal

View File

@ -33,6 +33,13 @@
#define __PRETTY_FUNCTION__ __FUNCTION__
#endif
// thread_local doesn't exist on VS2013 but it might soon? (who knows)
// to work after Microsoft has updated to be C++11 compliant
#if !(defined(thread_local)) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
#define thread_local __declspec(thread)
#endif
/** namespace for LOG() and CHECK() frameworks
* History lesson: Why the names 'g2' and 'g2log'?:
* The framework was made in my own free time as PUBLIC DOMAIN but the
@ -62,8 +69,12 @@ namespace g2 {
* This will be reset to default (does nothing) at initializeLogging(...);
*
* Example usage:
* Windows: g2::SetPreFatalHook([]{__debugbreak();}); // remember #include <intrin.h>
* Linux: g2::SetPreFatalHook([]{ raise(SIGTRAP); });
* Windows: g2::setFatalPreLoggingHook([]{__debugbreak();}); // remember #include <intrin.h>
* WARNING: '__debugbreak()' when not running in Debug in your Visual Studio IDE will likely
* trigger a recursive crash if used here. It should only be used when debugging
* in your Visual Studio IDE. Recursive crashes are handled but are unnecessary.
*
* Linux: g2::setFatalPreLoggingHook([]{ raise(SIGTRAP); });
*/
void setFatalPreLoggingHook(std::function<void(void)> pre_fatal_hook);

View File

@ -13,6 +13,7 @@
* ============================================================================*/
#include "stacktrace_windows.hpp"
#include "g2log.hpp"
#include <windows.h>
#include <DbgHelp.h>
#include <map>
@ -34,12 +35,11 @@
#define g2_MAP_PAIR_STRINGIFY(x) {x, #x}
namespace {
g2_thread_local size_t g_thread_local_recursive_crash_check = 0;
thread_local size_t g_thread_local_recursive_crash_check = 0;
const std::map<g2::SignalType, std::string> kExceptionsAsText = {
g2_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_DATATYPE_MISALIGNMENT)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO)
@ -56,8 +56,10 @@ const std::map<g2::SignalType, std::string> kExceptionsAsText = {
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_INVALID_DISPOSITION)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_STACK_OVERFLOW)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_BREAKPOINT)
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_SINGLE_STEP)
};

View File

@ -17,8 +17,6 @@
#error "stacktrace_win.cpp used but not on a windows system"
#endif
#define g2_thread_local __declspec(thread)
#include <string>
#include <windows.h>
#include "crashhandler.hpp"