Make handler stop flag atomic

This commit is contained in:
Julien Letessier 2026-01-15 16:27:14 +01:00
parent 37e8bbd86e
commit 65c55be6cd
5 changed files with 72 additions and 3 deletions

View File

@ -50,7 +50,7 @@ void Handler::run()
Response::init(); Response::init();
auto conf = mProxy->conf(); auto conf = mProxy->conf();
refreshServerPool(); refreshServerPool();
while (!mStop) { while (!mStop.load()) {
mEventLoop->wait(100000, this); mEventLoop->wait(100000, this);
postEvent(); postEvent();
long timeout = conf->clientTimeout(); long timeout = conf->clientTimeout();
@ -78,7 +78,7 @@ void Handler::run()
void Handler::stop() void Handler::stop()
{ {
mStop = true; mStop.store(true);
} }
void Handler::refreshServerPool() void Handler::refreshServerPool()

View File

@ -12,6 +12,7 @@
#include "Multiplexor.h" #include "Multiplexor.h"
#include "Stats.h" #include "Stats.h"
#include "LatencyMonitor.h" #include "LatencyMonitor.h"
#include "Sync.h"
#include "AcceptConnection.h" #include "AcceptConnection.h"
#include "ConnectConnectionPool.h" #include "ConnectConnectionPool.h"
#include "Proxy.h" #include "Proxy.h"
@ -114,7 +115,7 @@ private:
mAcceptConns.push_back(c); mAcceptConns.push_back(c);
} }
private: private:
bool mStop; Atomic<bool> mStop;
Proxy* mProxy; Proxy* mProxy;
Multiplexor* mEventLoop; Multiplexor* mEventLoop;
std::vector<ConnectConnectionPool*> mConnPool; std::vector<ConnectConnectionPool*> mConnPool;

View File

@ -0,0 +1,17 @@
/*
* Compile-only test to ensure Handler::mStop is atomic.
*/
#define private public
#include "../src/Handler.h"
#undef private
#include <type_traits>
#include <utility>
int main() {
using StopType = decltype(std::declval<Handler>().mStop);
static_assert(std::is_same<StopType, Atomic<bool>>::value,
"Handler::mStop should be atomic");
return 0;
}

View File

@ -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")

View File

@ -150,6 +150,7 @@ TESTS=(
"test/logger_thread_init.py" "test/logger_thread_init.py"
"test/logger_unbounded_logunit.py" "test/logger_unbounded_logunit.py"
"test/string_to_int.py" "test/string_to_int.py"
"test/handler_stop_atomic.py"
"test/pubsub_long_name.py" "test/pubsub_long_name.py"
"test/pubsub_large_message.py" "test/pubsub_large_message.py"
"test/transaction_forbid.py" "test/transaction_forbid.py"