From 65c55be6cdde4114938ec4de56d73198a26f642c Mon Sep 17 00:00:00 2001 From: Julien Letessier Date: Thu, 15 Jan 2026 16:27:14 +0100 Subject: [PATCH] Make handler stop flag atomic --- src/Handler.cpp | 4 +-- src/Handler.h | 3 ++- test/handler_stop_atomic.cpp | 17 ++++++++++++ test/handler_stop_atomic.py | 50 ++++++++++++++++++++++++++++++++++++ test/run.sh | 1 + 5 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 test/handler_stop_atomic.cpp create mode 100644 test/handler_stop_atomic.py diff --git a/src/Handler.cpp b/src/Handler.cpp index 5fa65d4..f12dff4 100644 --- a/src/Handler.cpp +++ b/src/Handler.cpp @@ -50,7 +50,7 @@ void Handler::run() Response::init(); auto conf = mProxy->conf(); refreshServerPool(); - while (!mStop) { + while (!mStop.load()) { mEventLoop->wait(100000, this); postEvent(); long timeout = conf->clientTimeout(); @@ -78,7 +78,7 @@ void Handler::run() void Handler::stop() { - mStop = true; + mStop.store(true); } void Handler::refreshServerPool() diff --git a/src/Handler.h b/src/Handler.h index a2fc55f..208d39b 100644 --- a/src/Handler.h +++ b/src/Handler.h @@ -12,6 +12,7 @@ #include "Multiplexor.h" #include "Stats.h" #include "LatencyMonitor.h" +#include "Sync.h" #include "AcceptConnection.h" #include "ConnectConnectionPool.h" #include "Proxy.h" @@ -114,7 +115,7 @@ private: mAcceptConns.push_back(c); } private: - bool mStop; + Atomic mStop; Proxy* mProxy; Multiplexor* mEventLoop; std::vector mConnPool; diff --git a/test/handler_stop_atomic.cpp b/test/handler_stop_atomic.cpp new file mode 100644 index 0000000..2a883f7 --- /dev/null +++ b/test/handler_stop_atomic.cpp @@ -0,0 +1,17 @@ +/* + * Compile-only test to ensure Handler::mStop is atomic. + */ + +#define private public +#include "../src/Handler.h" +#undef private + +#include +#include + +int main() { + using StopType = decltype(std::declval().mStop); + static_assert(std::is_same>::value, + "Handler::mStop should be atomic"); + return 0; +} diff --git a/test/handler_stop_atomic.py b/test/handler_stop_atomic.py new file mode 100644 index 0000000..aae8028 --- /dev/null +++ b/test/handler_stop_atomic.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +# +# Build and run the Handler::mStop atomic type check. +# + +import os +import platform +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", "handler_stop_atomic.cpp") + if not os.path.exists(src): + print("FAIL: handler_stop_atomic.cpp not found") + return False + + with tempfile.TemporaryDirectory() as tmp: + exe = os.path.join(tmp, "handler_stop_atomic") + cmd = [ + "g++", + "-std=c++11", + src, + "-o", + exe, + ] + sysname = platform.system() + if sysname == "Darwin": + cmd.insert(1, "-D_KQUEUE_") + elif sysname == "Linux": + cmd.insert(1, "-D_EPOLL_") + try: + subprocess.check_call(cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except Exception as exc: + print("FAIL: compile handler_stop_atomic:", exc) + return False + try: + subprocess.check_call([exe], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + except subprocess.CalledProcessError as exc: + print("FAIL: handler_stop_atomic returned", exc.returncode) + return False + return True + + +if __name__ == "__main__": + _ = parse_args("Handler stop atomic test") + root = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) + success = run_test(root) + exit_with_result(success, "handler stop atomic", "handler stop atomic") diff --git a/test/run.sh b/test/run.sh index 7a34a92..4d3200e 100755 --- a/test/run.sh +++ b/test/run.sh @@ -150,6 +150,7 @@ TESTS=( "test/logger_thread_init.py" "test/logger_unbounded_logunit.py" "test/string_to_int.py" + "test/handler_stop_atomic.py" "test/pubsub_long_name.py" "test/pubsub_large_message.py" "test/transaction_forbid.py"