diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..83fa468f Binary files /dev/null and b/.DS_Store differ diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 00000000..82b4dda0 Binary files /dev/null and b/docs/.DS_Store differ diff --git a/src/g3log.cpp b/src/g3log.cpp index 4299d9b4..fa35e41c 100644 --- a/src/g3log.cpp +++ b/src/g3log.cpp @@ -148,45 +148,48 @@ namespace g3 { message.get()->setExpression(boolean_expression); 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{std::make_unique(*(message._move_only.get()), fatal_signal)}; - // At destruction, flushes fatal message to g3LogWorker - // 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 - //..... OR it's in unit-test mode then we throw a std::runtime_error (and never hit sleep) - fatalCall(fatal_message); + saveFatalMessage(level, stack_trace, message, fatal_signal); } else { pushMessageToLogger(message); } } + void saveFatalMessage(const LEVELS& level, const char* stack_trace, g3::LogMessagePtr& message, int& fatal_signal) { + 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{std::make_unique(*(message._move_only.get()), fatal_signal)}; + // At destruction, flushes fatal message to g3LogWorker + // 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 + //..... OR it's in unit-test mode then we throw a std::runtime_error (and never hit sleep) + fatalCall(fatal_message); + } /** - * save the message to the logger. In case of called before the logger is instantiated - * the first message will be saved. Any following subsequent uninitialized log calls - * will be ignored. - * - * The first initialized log entry will also save the first uninitialized log message, if any - * @param log_entry to save to logger - */ + * save the message to the logger. In case of called before the logger is instantiated + * the first message will be saved. Any following subsequent uninitialized log calls + * will be ignored. + * + * The first initialized log entry will also save the first uninitialized log message, if any + * @param log_entry to save to logger + */ void pushMessageToLogger(LogMessagePtr incoming) { // todo rename to Push SavedMessage To Worker // Uninitialized messages are ignored but does not CHECK/crash the logger if (!internal::isLoggingInitialized()) { @@ -196,9 +199,8 @@ namespace g3 { err.append(g_first_uninitialized_msg->message()); std::string& str = g_first_uninitialized_msg->write(); str.clear(); - str.append(err); // replace content - std::cerr << str << std::endl; - }); + str.append(err); // replace content + std::cerr << str << std::endl; }); return; } @@ -207,10 +209,10 @@ namespace g3 { } /** Fatal call saved to logger. This will trigger SIGABRT or other fatal signal - * to exit the program. After saving the fatal message the calling thread - * will sleep forever (i.e. until the background thread catches up, saves the fatal - * message and kills the software with the fatal signal. - */ + * to exit the program. After saving the fatal message the calling thread + * will sleep forever (i.e. until the background thread catches up, saves the fatal + * message and kills the software with the fatal signal. + */ void pushFatalMessageToLogger(FatalMessagePtr message) { if (!isLoggingInitialized()) { std::ostringstream error; @@ -228,10 +230,10 @@ namespace g3 { } /** The default, initial, handling to send a 'fatal' event to g3logworker - * the caller will stay here, eternally, until the software is aborted - * ... in the case of unit testing it is the given "Mock" fatalCall that will - * define the behaviour. - */ + * the caller will stay here, eternally, until the software is aborted + * ... in the case of unit testing it is the given "Mock" fatalCall that will + * define the behaviour. + */ void fatalCall(FatalMessagePtr message) { g_fatal_to_g3logworker_function_ptr(FatalMessagePtr{std::move(message)}); } diff --git a/src/g3log/g3log.hpp b/src/g3log/g3log.hpp index 2a8539c8..37c54506 100644 --- a/src/g3log/g3log.hpp +++ b/src/g3log/g3log.hpp @@ -106,6 +106,8 @@ namespace g3 { void saveMessage(const char* message, const char* file, int line, const char* function, const LEVELS& level, const char* boolean_expression, int fatal_signal, const char* stack_trace); + void saveFatalMessage(const LEVELS& level, const char* stack_trace, g3::LogMessagePtr& message, int& fatal_signal); + // forwards the message to all sinks void pushMessageToLogger(LogMessagePtr log_entry);