void saveMessage(const char* entry, const char* file, int line, const char* function, const LEVELS& level, const char* boolean_expression, int fatal_signal, const char* stack_trace) { LEVELS msgLevel{level}; LogMessagePtr message{std2::make_unique<LogMessage>(file, line, function, msgLevel)}; 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)}; // 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 //..... OR it's in unit-test mode then we throw a std::runtime_error (and never hit sleep) fatalCall(fatal_message); } else { pushMessageToLogger(message); } }
/** 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, const char *boolean_expression, int fatal_signal, const char *stack_trace) { LEVELS msgLevel {level}; LogMessagePtr message {std2::make_unique<LogMessage>(file, line, function, msgLevel)}; message.get()->write().append(entry); 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 { std2::make_unique<FatalMessage>(*(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); } else { pushMessageToLogger(message); } }