mirror of
https://github.com/KjellKod/g3log.git
synced 2025-02-24 07:21:30 +01:00
Merge pull request #7 from KjellKod/windows-vector-exceptions
Windows vector exceptions
This commit is contained in:
commit
65846fdeaa
@ -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 "
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user