fix: serialize console output in fair::mq::tools::execute

- concurrent execute() calls print captured subprocess lines to
  std::cout from multiple threads; the standard allows that, but
  libstdc++ maintains the formatted-output state (ios_base::width)
  with plain reads and writes -- a data race ThreadSanitizer reports
  once libstdc++ itself is instrumented
- a mutex around the insertion also keeps whole lines from
  interleaving
This commit is contained in:
Dennis Klein
2026-06-10 16:12:35 +02:00
committed by Dennis Klein
parent 1597999aed
commit f08d42fcb8

View File

@@ -18,6 +18,7 @@
#include <chrono>
#include <csignal> // kill, signals
#include <iostream>
#include <mutex>
#include <sstream>
#include <stdexcept>
#include <thread>
@@ -40,10 +41,18 @@ class LinePrinter
, fPrefix(std::move(prefix))
{}
// prints line with prefix on both cout (thread-safe) and output stream
// prints line with prefix on both cout and output stream
void Print(const string& line)
{
cout << fair::mq::tools::ToString(fPrefix, line, "\n") << flush;
// Serialize: the standard allows concurrent insertion on std::cout,
// but libstdc++ maintains the formatted-output state (e.g.
// ios_base::width) with plain reads and writes that constitute data
// races; the lock also keeps whole lines from interleaving.
static mutex sCoutMutex;
{
lock_guard<mutex> lock(sCoutMutex);
cout << fair::mq::tools::ToString(fPrefix, line, "\n") << flush;
}
fOut << fPrefix << line << endl;
}