This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 8b9a0075cc Fix JSONRPC server shutdown race (#13461)
8b9a0075cc is described below
commit 8b9a0075cc62cff394da104b0c9cfb9aff65faa3
Author: Brian Neradt <[email protected]>
AuthorDate: Thu Jul 30 16:09:15 2026 -0500
Fix JSONRPC server shutdown race (#13461)
JSONRPC server shutdown can race with worker thread startup. When the
worker starts after stop_thread(), it restores the running flag and
polls a closed socket indefinitely. This causes test_jsonrpcserver and
process shutdown to hang.
This marks the socket server as running before the worker is created,
so a concurrent stop cannot be overwritten. It also passes the owning
server to the worker instead of relying on the mutable global server
pointer.
---
include/mgmt/rpc/server/IPCSocketServer.h | 2 +-
src/mgmt/rpc/server/IPCSocketServer.cc | 6 ++++--
src/mgmt/rpc/server/RPCServer.cc | 12 ++++++------
3 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/include/mgmt/rpc/server/IPCSocketServer.h
b/include/mgmt/rpc/server/IPCSocketServer.h
index 4ffe377d43..7c45204b13 100644
--- a/include/mgmt/rpc/server/IPCSocketServer.h
+++ b/include/mgmt/rpc/server/IPCSocketServer.h
@@ -144,7 +144,7 @@ private:
void close();
void late_check_peer_credentials(int peedFd, TSRPCHandlerOptions const
&options, swoc::Errata &errata) const;
- std::atomic_bool _running;
+ std::atomic_bool _running{false};
struct sockaddr_un _serverAddr;
int _socket{-1};
diff --git a/src/mgmt/rpc/server/IPCSocketServer.cc
b/src/mgmt/rpc/server/IPCSocketServer.cc
index e2b235650b..922db9b8ec 100644
--- a/src/mgmt/rpc/server/IPCSocketServer.cc
+++ b/src/mgmt/rpc/server/IPCSocketServer.cc
@@ -168,6 +168,10 @@ IPCSocketServer::init()
return ec;
}
+ // Set this before RPCServer creates the worker thread so an immediate stop
+ // cannot be overwritten when the worker eventually enters run().
+ _running.store(true);
+
return ec;
}
@@ -201,8 +205,6 @@
IPCSocketServer::poll_for_new_client(std::chrono::milliseconds timeout) const
void
IPCSocketServer::run()
{
- _running.store(true);
-
while (_running) {
// poll till socket it's ready.
if (!this->poll_for_new_client()) {
diff --git a/src/mgmt/rpc/server/RPCServer.cc b/src/mgmt/rpc/server/RPCServer.cc
index eb12135916..6c8a55afa6 100644
--- a/src/mgmt/rpc/server/RPCServer.cc
+++ b/src/mgmt/rpc/server/RPCServer.cc
@@ -59,13 +59,13 @@ RPCServer::~RPCServer()
void * /* static */
RPCServer::run_thread(void *a)
{
- void *ret = a;
- if (jsonrpcServer->_init) {
- jsonrpcServer->_rpcThread = jsonrpcServer->_init();
+ auto *server = static_cast<RPCServer *>(a);
+ if (server->_init) {
+ server->_rpcThread = server->_init();
}
- jsonrpcServer->_socketImpl->run();
+ server->_socketImpl->run();
Dbg(dbg_ctl, "Socket stopped");
- return ret;
+ return a;
}
void
@@ -75,7 +75,7 @@ RPCServer::start_thread(std::function<TSThread()> const
&cb_init, std::function<
_init = cb_init;
_destroy = cb_destroy;
- ink_thread_create(&_this_thread, run_thread, nullptr, 0, 0, nullptr);
+ ink_thread_create(&_this_thread, run_thread, this, 0, 0, nullptr);
}
void