]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/net: postpone the close() using yield() 47152/head
authorKefu Chai <tchaikov@gmail.com>
Mon, 18 Jul 2022 14:35:19 +0000 (22:35 +0800)
committerKefu Chai <tchaikov@gmail.com>
Mon, 18 Jul 2022 15:03:32 +0000 (23:03 +0800)
otherwise we'd erase an element in a container when we are still
iterating through it.

Fixes: https://tracker.ceph.com/issues/56589
Signed-off-by: Kefu Chai <tchaikov@gmail.com>
src/crimson/net/Protocol.h

index 0343f026025aa9a7fcb56180e651f1f8513abf59..34eb8a60e7a34b5bca74ca8414336064904aa46f 100644 (file)
@@ -5,6 +5,7 @@
 
 #include <seastar/core/gate.hh>
 #include <seastar/core/shared_future.hh>
+#include <seastar/util/later.hh>
 
 #include "crimson/common/gated.h"
 #include "crimson/common/log.h"
@@ -34,11 +35,18 @@ class Protocol {
   // Reentrant closing
   void close(bool dispatch_reset, std::optional<std::function<void()>> f_accept_new=std::nullopt);
   seastar::future<> close_clean(bool dispatch_reset) {
-    close(dispatch_reset);
-    // it can happen if close_clean() is called inside Dispatcher::ms_handle_reset()
-    // which will otherwise result in deadlock
-    assert(close_ready.valid());
-    return close_ready.get_future();
+    // yield() so that close(dispatch_reset) can be called *after*
+    // close_clean() is applied to all connections in a container using
+    // seastar::parallel_for_each(). otherwise, we could erase a connection in
+    // the container when seastar::parallel_for_each() is still iterating in
+    // it. that'd lead to a segfault.
+    return seastar::yield().then([this, dispatch_reset] {
+      close(dispatch_reset);
+      // it can happen if close_clean() is called inside Dispatcher::ms_handle_reset()
+      // which will otherwise result in deadlock
+      assert(close_ready.valid());
+      return close_ready.get_future();
+    });
   }
 
   virtual void start_connect(const entity_addr_t& peer_addr,