summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan-Marek Glogowski <glogow@fbihome.de>2020-07-01 18:06:28 +0200
committerMichael Stahl <michael.stahl@allotropia.de>2022-03-10 13:50:34 +0100
commit5e3d3f4b276916ddeb7b680c9513dc6d618fc3be (patch)
tree1f10f76f16fa98fe32781afc8e29b0de81848f43
parentf1843592b03b111daeb446e410b606e170dfa67e (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.cxx3
-rw-r--r--include/sal/log.hxx41
-rw-r--r--sal/osl/all/log.cxx42
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;