lg2: Add mutex to avoid stderr line corruption
Use of a mutex, along with flushing after every line, prevents threads
in multithreaded programs from corrupting each other's stderr logging
lines. As for the D-Bus journal messages, they are already atomic, not
needing this fix.
Tested: The corruption appears fixed
https://gist.github.com/Krellan/d5d9942cb5ab405c9689e4eb4bb75cf0
Change-Id: I1db88139406eb617aa713740d5ccb6c9420ca773
Signed-off-by: Josh Lehan <krellan@google.com>
diff --git a/lib/lg2_logger.cpp b/lib/lg2_logger.cpp
index 81f085d..fcf129f 100644
--- a/lib/lg2_logger.cpp
+++ b/lib/lg2_logger.cpp
@@ -10,7 +10,9 @@
#include <cstdarg>
#include <cstdio>
#include <iostream>
+#include <mutex>
#include <source_location>
+#include <sstream>
#include <vector>
namespace lg2::details
@@ -146,11 +148,13 @@
const char* format = defaultFormat;
+ std::stringstream stream;
+
while (*format)
{
if (*format != '%')
{
- std::cerr << *format;
+ stream << *format;
++format;
continue;
}
@@ -160,31 +164,31 @@
{
case '%':
case '\0':
- std::cerr << '%';
+ stream << '%';
break;
case 'f':
- std::cerr << s.function_name();
+ stream << s.function_name();
break;
case 'F':
- std::cerr << s.file_name();
+ stream << s.file_name();
break;
case 'l':
- std::cerr << static_cast<uint64_t>(l);
+ stream << static_cast<uint64_t>(l);
break;
case 'L':
- std::cerr << s.line();
+ stream << s.line();
break;
case 'm':
- std::cerr << m;
+ stream << m;
break;
default:
- std::cerr << '%' << *format;
+ stream << '%' << *format;
break;
}
@@ -194,7 +198,13 @@
}
}
- std::cerr << std::endl;
+ static std::mutex mutex;
+
+ // Prevent multiple threads from clobbering the stderr lines of each other
+ std::scoped_lock lock(mutex);
+
+ // Ensure this line makes it out before releasing mutex for next line
+ std::cerr << stream.str() << std::endl;
}
// Use the cerr output method if we are on a TTY or if explicitly set via
diff --git a/lib/meson.build b/lib/meson.build
index 1de91ec..9c65652 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -4,10 +4,13 @@
subdir('include/phosphor-logging')
+threads_dep = dependency('threads')
+
phosphor_logging_deps = [
pdi_dep,
sdbusplus_dep,
systemd_dep,
+ threads_dep
]
phosphor_logging_lib = library(