__debugbreak in windows can easily cause recursive crashes if you are

NOT in debug mode in your visual IDE
This commit is contained in:
Kjell Hedstrom 2015-03-02 01:14:03 -07:00
parent e2117fcc17
commit a5d922de49
5 changed files with 50 additions and 10 deletions

View File

@ -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 "

View File

@ -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

View File

@ -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);

View File

@ -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)
}; };

View File

@ -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"