From bba825815a70821f9005f3f3ab5d818c13624329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kjell=20Hedstr=C3=B6m=20-=20seeking=20Senior=20Engineering?= =?UTF-8?q?=20roles=20as=20well=20as=20contract=20opportunities?= Date: Tue, 5 Dec 2023 21:04:01 -0700 Subject: [PATCH] refactor fatal call (#511) * refactor fatal handling --- .DS_Store | Bin 0 -> 8196 bytes docs/.DS_Store | Bin 0 -> 6148 bytes src/g3log.cpp | 90 ++++++++++++++++++++++---------------------- src/g3log/g3log.hpp | 2 + 4 files changed, 48 insertions(+), 44 deletions(-) create mode 100644 .DS_Store create mode 100644 docs/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..83fa468f4831eb3282c575a2ecd56bb572662927 GIT binary patch literal 8196 zcmeHM&2G~`5T0#Q;t*N_0;xzKS#YgNN-3h^lBNwPQcIyp;Q%N&iCe5Xc9fr{s4B`G zo`F~3%!}|C+&RHFyKZE=ap6)_sk_nc?Ar6q?tVM7_Buo)iv8vS(JT=e$SiYN6k`(K z=X@ef1XpfD3gC%$$e~@Dr;pS+p{*}y1~dbj0nLDBKr?V27{D`|lacV;S9f)(8PE(| zNCtR+Fp*gn0y$JtZXGD(5dboU%QB&kbAZH{fh+`asHB9#raC={04jnbhEQH z?U5ZreU71KXce|?=z18li(fMKR}4Fq)XT(fOp|-rP~)L>%%)2{TN*{bci zEzf6ykVNo&qG{D0m0wUBO?WK4K>1K6kN1Hk{i= z$XReWTRLI`EgueG%OLjPL_K5<>Mk6F!_CIRCIt~fFVaT_h)t@Tg1~$uh?xNKFChzu zh+xxjp)wq*1ox{@DLQ|4i-`7R@U(aALKq=`Y>aO@%-N?9XVaKXJH$vL6NFHUAZOv` z+Zf+Ef@}*Te2G>GqpYG`MQsE3*Re)iPYAn+y^OT7f|c4xKrpl6v8S5m0hZ+1CVlWp%w59Lu$W5Qo9>y244exFL~5V;FU1VJ1v$l!+ z9+?yC4V9D-6!JI@DUaijqdyE$H=)XyLLi4q;tJCL{}8}$MEd#9?~VHTFJ16L7JmR# CA2&w; literal 0 HcmV?d00001 diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..82b4dda05d9969f3fc310ab2dd39fa001ea869e8 GIT binary patch literal 6148 zcmeHKOG*Pl5Uq|uf83Hk*`QdVQF1&-_){Weo}#_31Y=-P1&5TFb#XQH_WyP{#5engZebtT`z;OBHA&#vKhhlepiT z#J${TH7Enhz+Yp4zujGG(iL^6LFw<87ln6d<5NURue-4k^=V0ST2KtHh;D&1^t!Mt zXiQTY6~=33;#H}KIAfa7V6&Gw%XsZ0dkl{uD!50^zVr&}H_sW*L-CxV#u@T)?r*9! z9~ti>BX3n*X@rO`Uc>`LxL8-kPq+&U&n@?Eh_C-{ROAWrQ+X^JFYl6{tG3Rw zRju+ge1DX#@&g92XR}mz4Ny@AlmTVHXMop-0LmCTOf1UMfkuu1z%tAt=<{y_`veX{ zhlxepff(xww64Y-F^qMGJ#gbfhlxe&PR1QRjLU4?3B^cu#1CXRnb4xP%78MEW?;u& z)_DKF+F`!uhl=1{ Xz#U-dFtG>=M1KT?25ppqUuED6J8;4P literal 0 HcmV?d00001 diff --git a/src/g3log.cpp b/src/g3log.cpp index 4299d9b..fa35e41 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 2a8539c..37c5450 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);