From abe75e40a29a71c63871422f931968415697ad65 Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Thu, 15 Jan 2026 16:29:08 +0100 Subject: [PATCH] Make logger stop flag atomic --- src/Logger.cpp | 8 +++---- src/Logger.h | 2 +- test/logger_stop_atomic.cpp | 17 ++++++++++++++ test/logger_stop_atomic.py | 44 +++++++++++++++++++++++++++++++++++++ test/run.sh | 1 + 5 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 test/logger_stop_atomic.cpp create mode 100644 test/logger_stop_atomic.py diff --git a/src/Logger.cpp b/src/Logger.cpp index d951660..7be05ee 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -122,7 +122,7 @@ void Logger::start() void Logger::stop() { - mStop = true; + mStop.store(true); std::unique_lock lck(mMtx); mCond.notify_one(); } @@ -131,11 +131,11 @@ void Logger::run() { std::vector logs(mFree.capacity()); logs.resize(0); - while (!mStop) { + while (!mStop.load()) { long missLogs = 0; do { std::unique_lock lck(mMtx); - while (mLogs.empty() && !mStop) { + while (mLogs.empty() && !mStop.load()) { mCond.wait(lck); } logs.swap(mLogs); @@ -211,7 +211,7 @@ LogUnit* Logger::getLogUnit() ++mLogUnitCnt; log = new LogUnit(); } else { - while (mFree.empty() && !mStop) { + while (mFree.empty() && !mStop.load()) { mCond.wait(lck); } if (!mFree.empty()) { diff --git a/src/Logger.h b/src/Logger.h index 24c6e69..b36c6e9 100644 --- a/src/Logger.h +++ b/src/Logger.h @@ -101,7 +101,7 @@ private: LogUnit* getLogUnit(); void run(); private: - bool mStop; + Atomic mStop; bool mAllowMissLog; AtomicLong mMissLogs; int mLogSample[LogLevel::Sentinel]; diff --git a/test/logger_stop_atomic.cpp b/test/logger_stop_atomic.cpp new file mode 100644 index 0000000..fde8720 --- /dev/null +++ b/test/logger_stop_atomic.cpp @@ -0,0 +1,17 @@ +/* + * Compile-only test to ensure Logger::mStop is atomic. + */ + +#define private public +#include "../src/Logger.h" +#undef private + +#include +#include + +int main() { + using StopType = decltype(std::declval().mStop); + static_assert(std::is_same>::value, + "Logger::mStop should be atomic"); + return 0; +} diff --git a/test/logger_stop_atomic.py b/test/logger_stop_atomic.py new file mode 100644 index 0000000..eba2b90 --- /dev/null +++ b/test/logger_stop_atomic.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +# +# Build and run the Logger::mStop atomic type check. +# + +import os +import subprocess +import tempfile +from test_util import parse_args, exit_with_result + + +def run_test(project_root): + src = os.path.join(project_root, "test", "logger_stop_atomic.cpp") + if not os.path.exists(src): + print("FAIL: logger_stop_atomic.cpp not found") + return False + + with tempfile.TemporaryDirectory() as tmp: + exe = os.path.join(tmp, "logger_stop_atomic") + cmd = [ + "g++", + "-std=c++11", + src, + "-o", + exe, + ] + try: + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except Exception as exc: + print("FAIL: compile logger_stop_atomic:", exc) + return False + try: + subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as exc: + print("FAIL: logger_stop_atomic returned", exc.returncode) + return False + return True + + +if __name__ == "__main__": + _ = parse_args("Logger stop atomic test") + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + success = run_test(root) + exit_with_result(success, "logger stop atomic", "logger stop atomic") diff --git a/test/run.sh b/test/run.sh index 4d3200e..6d918c5 100755 --- a/test/run.sh +++ b/test/run.sh @@ -151,6 +151,7 @@ TESTS=( "test/logger_unbounded_logunit.py" "test/string_to_int.py" "test/handler_stop_atomic.py" + "test/logger_stop_atomic.py" "test/pubsub_long_name.py" "test/pubsub_large_message.py" "test/transaction_forbid.py"