]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common/async: async_cond::notify/cancel must post to handler's associated executor
authorShilpa Jagannath <smanjara@redhat.com>
Fri, 5 Jun 2026 18:42:35 +0000 (14:42 -0400)
committerCasey Bodley <cbodley@redhat.com>
Thu, 25 Jun 2026 16:54:34 +0000 (12:54 -0400)
RGWDeleteMultiObj spawns child coroutines via spawn_throttle to delete
objects in parallel. each child coroutine carries the connection strand
as its associated executor, serializing concurrent operations on shared
state like the response formatter and ops_log_entries.

but in multisite env, concurrent deletions in the same bucket shard
contend on async_cond in RGWDataChangesLog::add_entry(). when notify()
fires, waiting coroutines resume on the raw io_context executor
instead of their connection strand, breaking the serialization that prevents data
races in send_partial_response()

any_completion_handler doesn't support post(). so post() to the
default executor and dispatch to the associated executor from there

Signed-off-by: Shilpa Jagannath <smanjara@redhat.com>
(cherry picked from commit 04aceefad0ef2b0186b0854ae28b4fbc4ffa51c3)

src/common/async/async_cond.h

index 8f6ccd632a3a8069df2d8ba641af5fdb0aaa7285..b27fb6dcb940f794fb7f9a660927d863937d1ab6 100644 (file)
@@ -26,6 +26,7 @@
 #include <boost/asio/any_completion_handler.hpp>
 #include <boost/asio/append.hpp>
 #include <boost/asio/async_result.hpp>
+#include <boost/asio/bind_executor.hpp>
 #include <boost/asio/consign.hpp>
 #include <boost/asio/error.hpp>
 #include <boost/asio/execution_context.hpp>
@@ -55,8 +56,8 @@ class async_cond : public service_list_base_hook {
 
   std::mutex m;
   std::vector<std::pair<
-    boost::asio::any_completion_handler<
-    void(boost::system::error_code)>, std::unique_lock<BasicLockable>*>> handlers;
+    boost::asio::any_completion_handler<void(boost::system::error_code)>,
+    std::unique_lock<BasicLockable>*>> handlers;
 
   void service_shutdown() {
     std::unique_lock l(m);
@@ -132,12 +133,13 @@ public:
       handlers.resize(0);
       l.unlock();
       for (auto&& [handler, lock] : workhandlers) {
+       auto ex = asio::get_associated_executor(handler, executor);
        asio::post(executor,
-                  [handler = std::move(handler), lock = lock]() mutable {
-                    lock->lock();
-                    std::move(handler)(sys::error_code{});
-                  });
-
+                  asio::bind_executor(ex,
+                    [handler = std::move(handler), lock = lock]() mutable {
+                      lock->lock();
+                      std::move(handler)(sys::error_code{});
+                    }));
       }
     }
   }
@@ -154,12 +156,13 @@ public:
       handlers.resize(0);
       l.unlock();
       for (auto&& [handler, lock] : workhandlers) {
+       auto ex = asio::get_associated_executor(handler, executor);
        asio::post(executor,
-                  [handler = std::move(handler), lock = lock]() mutable {
-                    lock->lock();
-                    std::move(handler)(asio::error::operation_aborted);
-                  });
-
+                  asio::bind_executor(ex,
+                    [handler = std::move(handler), lock = lock]() mutable {
+                      lock->lock();
+                      std::move(handler)(asio::error::operation_aborted);
+                    }));
       }
     }
   }