This is an automated email from the ASF dual-hosted git repository.

git-hulk pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new d56980a82 fix(server): prevent connection migration during OnRead 
(#3715)
d56980a82 is described below

commit d56980a8207a2eeda2c12f64b5419ef394d16aad
Author: hulk <[email protected]>
AuthorDate: Fri Oct 23 17:33:02 2026 +0800

    fix(server): prevent connection migration during OnRead (#3715)
    
    A discarded scope guard in `Connection::OnRead()` lets worker resizing
    migrate a connection while it is still processing requests.
    
    The temporary guard is destroyed at the end of its creation statement,
    clearing `is_running_` immediately. The migration check then treats the
    connection as idle even though the read callback has not returned.
    
    Keep the guard active until the callback finishes, and cancel cleanup
    when closing deletes the connection. Mark `MakeScopeExit()` as
    `[[nodiscard]]` so the compiler diagnoses accidentally discarded guards.
    
    Reference: [CI failure in `TestDynamicChangeWorkerThread` (Ubuntu GCC
    
TSan)](https://github.com/apache/kvrocks/actions/runs/39618363098/job/119287428395).
    
    Assistant-By GPT-6
---
 src/common/scope_exit.h        | 2 +-
 src/server/redis_connection.cc | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/common/scope_exit.h b/src/common/scope_exit.h
index 2faeddfb1..0fd47fd4d 100644
--- a/src/common/scope_exit.h
+++ b/src/common/scope_exit.h
@@ -47,6 +47,6 @@ struct ScopeExit {
 
 // use CTAD in C++17 or above
 template <typename F>
-ScopeExit<F> MakeScopeExit(F&& f, bool enabled = true) {
+[[nodiscard]] ScopeExit<F> MakeScopeExit(F&& f, bool enabled = true) {
   return ScopeExit<F>(std::forward<F>(f), enabled);
 }
diff --git a/src/server/redis_connection.cc b/src/server/redis_connection.cc
index f212966d8..9721aafbe 100644
--- a/src/server/redis_connection.cc
+++ b/src/server/redis_connection.cc
@@ -152,7 +152,7 @@ void Connection::Detach() { owner_->DetachConnection(this); 
}
 
 void Connection::OnRead([[maybe_unused]] struct bufferevent *bev) {
   is_running_ = true;
-  MakeScopeExit([this] { is_running_ = false; });
+  auto reset_running = MakeScopeExit([this] { is_running_ = false; });
 
   SetLastInteraction();
   auto s = req_.Tokenize(Input());
@@ -165,6 +165,8 @@ void Connection::OnRead([[maybe_unused]] struct bufferevent 
*bev) {
 
   ExecuteCommands(req_.GetCommands());
   if (IsFlagEnabled(kCloseAsync)) {
+    // Close() deletes this, so the guard must not access it afterward.
+    reset_running.Disable();
     Close();
   }
 }

Reply via email to