mirror of
https://github.com/KjellKod/g3log.git
synced 2024-12-12 10:23:50 +01:00
__debugbreak in windows can easily cause recursive crashes if you are
NOT in debug mode in your visual IDE
This commit is contained in:
parent
e2117fcc17
commit
a5d922de49
@ -233,10 +233,18 @@ void ChooseFatalExit() {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void breakHere() {
|
||||||
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
|
__debugbreak();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
auto logger_n_handle = g2::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
|
auto logger_n_handle = g2::LogWorker::createWithDefaultLogger(argv[0], path_to_log_file);
|
||||||
g2::initializeLogging(logger_n_handle.worker.get());
|
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::future<std::string> log_file_name = logger_n_handle.sink->call(&g2::FileSink::fileName);
|
||||||
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
|
std::cout << "**** G3LOG FATAL EXAMPLE ***\n\n"
|
||||||
<< "Choose your type of fatal exit, then "
|
<< "Choose your type of fatal exit, then "
|
||||||
|
@ -41,6 +41,8 @@ std::once_flag g_save_first_unintialized_flag;
|
|||||||
const std::function<void(void)> g_pre_fatal_hook_that_does_nothing = []{ /*does nothing */};
|
const std::function<void(void)> g_pre_fatal_hook_that_does_nothing = []{ /*does nothing */};
|
||||||
std::function<void(void)> g_fatal_pre_logging_hook;
|
std::function<void(void)> g_fatal_pre_logging_hook;
|
||||||
|
|
||||||
|
|
||||||
|
g2_thread_local size_t g_fatal_hook_recursive_counter = {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -82,6 +84,8 @@ void initializeLogging(LogWorker* bgworker) {
|
|||||||
* so please call this function, if you ever need to, after initializeLogging(...)
|
* so please call this function, if you ever need to, after initializeLogging(...)
|
||||||
*/
|
*/
|
||||||
void setFatalPreLoggingHook(std::function<void(void)> pre_fatal_hook) {
|
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;
|
g_fatal_pre_logging_hook = pre_fatal_hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +142,7 @@ bool shutDownLoggingForActiveOnly(LogWorker* active) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** explicits copy of all input. This is makes it possibly to use g3log across dynamically loaded libraries
|
/** explicits copy of all input. This is makes it possibly to use g3log across dynamically loaded libraries
|
||||||
* i.e. (dlopen + dlsym) */
|
* i.e. (dlopen + dlsym) */
|
||||||
void saveMessage(const char* entry, const char* file, int line, const char* function, const LEVELS& level,
|
void saveMessage(const char* entry, const char* file, int line, const char* function, const LEVELS& level,
|
||||||
@ -147,11 +152,28 @@ void saveMessage(const char* entry, const char* file, int line, const char* func
|
|||||||
message.get()->write().append(entry);
|
message.get()->write().append(entry);
|
||||||
message.get()->setExpression(boolean_expression);
|
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_local 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 > 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
|
// At destruction, flushes fatal message to g2LogWorker
|
||||||
// either we will stay here until the background worker has received the fatal
|
// 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
|
// message, flushed the crash message to the sinks and exits with the same fatal signal
|
||||||
|
@ -33,6 +33,16 @@
|
|||||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// thread_local doesn't exist on VS2013 but it might soon? (who knows)
|
||||||
|
// to avoid future issues, let's define g2_thread_local that should continue
|
||||||
|
// to work after Microsoft has updated to be C++11 compliant
|
||||||
|
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
|
||||||
|
#define g2_thread_local __declspec(thread)
|
||||||
|
#else
|
||||||
|
#define g2_thread_local thread_local
|
||||||
|
#endif
|
||||||
|
|
||||||
/** namespace for LOG() and CHECK() frameworks
|
/** namespace for LOG() and CHECK() frameworks
|
||||||
* History lesson: Why the names 'g2' and 'g2log'?:
|
* History lesson: Why the names 'g2' and 'g2log'?:
|
||||||
* The framework was made in my own free time as PUBLIC DOMAIN but the
|
* The framework was made in my own free time as PUBLIC DOMAIN but the
|
||||||
@ -62,8 +72,8 @@ namespace g2 {
|
|||||||
* This will be reset to default (does nothing) at initializeLogging(...);
|
* This will be reset to default (does nothing) at initializeLogging(...);
|
||||||
*
|
*
|
||||||
* Example usage:
|
* Example usage:
|
||||||
* Windows: g2::SetPreFatalHook([]{__debugbreak();}); // remember #include <intrin.h>
|
* Windows: g2::setFatalPreLoggingHook([]{__debugbreak();}); // remember #include <intrin.h>
|
||||||
* Linux: g2::SetPreFatalHook([]{ raise(SIGTRAP); });
|
* Linux: g2::setFatalPreLoggingHook([]{ raise(SIGTRAP); });
|
||||||
*/
|
*/
|
||||||
void setFatalPreLoggingHook(std::function<void(void)> pre_fatal_hook);
|
void setFatalPreLoggingHook(std::function<void(void)> pre_fatal_hook);
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
* ============================================================================*/
|
* ============================================================================*/
|
||||||
|
|
||||||
#include "stacktrace_windows.hpp"
|
#include "stacktrace_windows.hpp"
|
||||||
|
#include "g2log.hpp"
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <DbgHelp.h>
|
#include <DbgHelp.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -39,7 +40,6 @@ g2_thread_local size_t g_thread_local_recursive_crash_check = 0;
|
|||||||
const std::map<g2::SignalType, std::string> kExceptionsAsText = {
|
const std::map<g2::SignalType, std::string> kExceptionsAsText = {
|
||||||
g2_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION)
|
g2_MAP_PAIR_STRINGIFY(EXCEPTION_ACCESS_VIOLATION)
|
||||||
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_ARRAY_BOUNDS_EXCEEDED)
|
, 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_DATATYPE_MISALIGNMENT)
|
||||||
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND)
|
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DENORMAL_OPERAND)
|
||||||
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_FLT_DIVIDE_BY_ZERO)
|
, 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_INVALID_DISPOSITION)
|
||||||
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION)
|
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_NONCONTINUABLE_EXCEPTION)
|
||||||
, g2_MAP_PAIR_STRINGIFY(EXCEPTION_PRIV_INSTRUCTION)
|
, 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_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"
|
#error "stacktrace_win.cpp used but not on a windows system"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define g2_thread_local __declspec(thread)
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "crashhandler.hpp"
|
#include "crashhandler.hpp"
|
||||||
|
Loading…
Reference in New Issue
Block a user