diff options
author | Jan-Marek Glogowski <glogow@fbihome.de> | 2020-07-01 18:06:28 +0200 |
---|---|---|
committer | Michael Stahl <michael.stahl@allotropia.de> | 2022-03-10 13:50:34 +0100 |
commit | 5e3d3f4b276916ddeb7b680c9513dc6d618fc3be (patch) | |
tree | 1f10f76f16fa98fe32781afc8e29b0de81848f43 | |
parent | f1843592b03b111daeb446e410b606e170dfa67e (diff) |
Allow making SAL_LOG based output fatal
This introduces the [+-]FATAL marker for SAL_LOG. This way you can
set part of the matching SAL_LOG string to std::abort on match.
The example "SAL_LOG=+FATAL+WARN.vcl.scheduler-FATAL+INFO" will
abort for any "+WARN.vcl.scheduler" match, but will just print all
additional "+INFO" logs.
Change-Id: Ib77f194a78f5165e6c885c82374ae41293815ee9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97651
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
(cherry picked from commit b9d93fc47b2489764e251a11572fccef872df4e9)
-rw-r--r-- | compilerplugins/clang/stringconcatliterals.cxx | 3 | ||||
-rw-r--r-- | include/sal/log.hxx | 41 | ||||
-rw-r--r-- | sal/osl/all/log.cxx | 42 |
3 files changed, 71 insertions, 15 deletions
diff --git a/compilerplugins/clang/stringconcatliterals.cxx b/compilerplugins/clang/stringconcatliterals.cxx index 0f26f4f553bc..0b52bd0c9b4f 100644 --- a/compilerplugins/clang/stringconcatliterals.cxx +++ b/compilerplugins/clang/stringconcatliterals.cxx @@ -109,7 +109,8 @@ bool StringConcatLiterals::VisitCallExpr(CallExpr const * expr) { compiler.getSourceManager().getSpellingLoc( compiler.getSourceManager().getImmediateMacroCallerLoc( compiler.getSourceManager().getImmediateMacroCallerLoc( - compat::getBeginLoc(expr))))), + compiler.getSourceManager().getImmediateMacroCallerLoc( + compat::getBeginLoc(expr)))))), SRCDIR "/include/tools/diagnose_ex.h")) return true; diff --git a/include/sal/log.hxx b/include/sal/log.hxx index f85c7d882134..d4de09c201b4 100644 --- a/include/sal/log.hxx +++ b/include/sal/log.hxx @@ -26,11 +26,20 @@ /// @cond INTERNAL +enum sal_detail_LogAction +{ + SAL_DETAIL_LOG_ACTION_IGNORE, + SAL_DETAIL_LOG_ACTION_LOG, + SAL_DETAIL_LOG_ACTION_FATAL +}; + extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log( sal_detail_LogLevel level, char const * area, char const * where, char const * message, sal_uInt32 backtraceDepth); -extern "C" SAL_DLLPUBLIC sal_Bool SAL_CALL sal_detail_log_report( +// the return value is actually "enum sal_detail_LogAction", but due to ABI +// compatibility, it's left as the original "sal_Bool" / "unsigned char". +extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report( sal_detail_LogLevel level, char const * area); namespace sal { namespace detail { @@ -113,9 +122,9 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { } } -#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \ - do { \ - if ((condition) && sal_detail_log_report(level, area)) { \ +// to prevent using a local variable, which can eventually shadow, +// resulting in compiler warnings (or even errors with -Werror) +#define SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream) \ if (sizeof ::sal::detail::getResult( \ ::sal::detail::StreamStart() << stream) == 1) \ { \ @@ -129,6 +138,22 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { sal_detail_stream << stream; \ ::sal::detail::log( \ (level), (area), (where), sal_detail_stream, 0); \ + } + +#define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \ + do { \ + if (condition) \ + { \ + switch (sal_detail_log_report(level, area)) \ + { \ + case SAL_DETAIL_LOG_ACTION_IGNORE: break; \ + case SAL_DETAIL_LOG_ACTION_LOG: \ + SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \ + break; \ + case SAL_DETAIL_LOG_ACTION_FATAL: \ + SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \ + std::abort(); \ + break; \ } \ } \ } while (false) @@ -238,7 +263,7 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { <switch> ::= <sense><item> <sense> ::= "+"|"-" <item> ::= <flag>|<level>("."<area>)? - <flag> ::= "TIMESTAMP"|"RELATIVETIMER" + <flag> ::= "TIMESTAMP"|"RELATIVETIMER"|"FATAL" <level> ::= "INFO"|"WARN" @endverbatim @@ -255,6 +280,12 @@ inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) { the level switch(es)) to be prefixed by a relative timestamp in seconds since the first output line like 1.312. + The "+FATAL" flag will cause later matching rules to log and call + std::abort. This can be disabled at some later point by using the + "-FATAL" flag before specifying additional rules. The flag will just + abort on positive rules, as it doesn't seem to make sense to abort + on ignored output. + If both +TIMESTAMP and +RELATIVETIMER are specified, they are output in that order. diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx index 5a6ffdff9110..39ea42d7e130 100644 --- a/sal/osl/all/log.cxx +++ b/sal/osl/all/log.cxx @@ -344,7 +344,12 @@ void sal_detail_logFormat( sal_detail_LogLevel level, char const * area, char const * where, char const * format, ...) { - if (sal_detail_log_report(level, area)) { + const sal_detail_LogAction eAction + = static_cast<sal_detail_LogAction>(sal_detail_log_report(level, area)); + if (eAction == SAL_DETAIL_LOG_ACTION_IGNORE) + return; + + { std::va_list args; va_start(args, format); char buf[1024]; @@ -358,11 +363,15 @@ void sal_detail_logFormat( sal_detail_log(level, area, where, buf, 0); va_end(args); } + + if (eAction == SAL_DETAIL_LOG_ACTION_FATAL) + std::abort(); } -sal_Bool sal_detail_log_report(sal_detail_LogLevel level, char const * area) { +unsigned char sal_detail_log_report(sal_detail_LogLevel level, char const * area) +{ if (level == SAL_DETAIL_LOG_LEVEL_DEBUG) { - return true; + return SAL_DETAIL_LOG_ACTION_LOG; } assert(area != nullptr); static char const* const env = [] { @@ -378,17 +387,26 @@ sal_Bool sal_detail_log_report(sal_detail_LogLevel level, char const * area) { // no matching switches at all, the result will be negative (and // initializing with 1 is safe as the length of a valid switch, even // without the "+"/"-" prefix, will always be > 1) + bool senseFatal[2] = { false, false }; bool seenWarn = false; + bool bFlagFatal = false; for (char const * p = env;;) { Sense sense; switch (*p++) { case '\0': + { if (level == SAL_DETAIL_LOG_LEVEL_WARN && !seenWarn) return sal_detail_log_report(SAL_DETAIL_LOG_LEVEL_INFO, area); - return senseLen[POSITIVE] >= senseLen[NEGATIVE]; - // if a specific item is both positive and negative - // (senseLen[POSITIVE] == senseLen[NEGATIVE]), default to - // positive + + sal_detail_LogAction eAction = SAL_DETAIL_LOG_ACTION_IGNORE; + // if a specific item is positive and negative (==), default to positive + if (senseLen[POSITIVE] >= senseLen[NEGATIVE]) + { + if (senseFatal[POSITIVE]) eAction = SAL_DETAIL_LOG_ACTION_FATAL; + else eAction = SAL_DETAIL_LOG_ACTION_LOG; + } + return eAction; + } case '+': sense = POSITIVE; break; @@ -396,7 +414,7 @@ sal_Bool sal_detail_log_report(sal_detail_LogLevel level, char const * area) { sense = NEGATIVE; break; default: - return true; // upon an illegal SAL_LOG value, enable everything + return SAL_DETAIL_LOG_ACTION_LOG; // upon an illegal SAL_LOG value, enable everything } char const * p1 = p; while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') { @@ -409,13 +427,17 @@ sal_Bool sal_detail_log_report(sal_detail_LogLevel level, char const * area) { { match = level == SAL_DETAIL_LOG_LEVEL_WARN; seenWarn = true; + } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("FATAL"))) + { + bFlagFatal = (sense == POSITIVE); + match = false; } else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP")) || equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER"))) { // handled later match = false; } else { - return true; + return SAL_DETAIL_LOG_ACTION_LOG; // upon an illegal SAL_LOG value, everything is considered // positive } @@ -432,9 +454,11 @@ sal_Bool sal_detail_log_report(sal_detail_LogLevel level, char const * area) { && equalStrings(p1, n, area, n))) { senseLen[sense] = p2 - p; + senseFatal[sense] = bFlagFatal; } } else { senseLen[sense] = p1 - p; + senseFatal[sense] = bFlagFatal; } } p = p2; |