From edbe8725fc79c29ead7c2717dc2db49f9de23cc2 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 18 Jul 2022 22:35:19 +0800 Subject: [PATCH] crimson/net: postpone the close() using yield() 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 --- src/crimson/net/Protocol.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/crimson/net/Protocol.h b/src/crimson/net/Protocol.h index 0343f026025aa..34eb8a60e7a34 100644 --- a/src/crimson/net/Protocol.h +++ b/src/crimson/net/Protocol.h @@ -5,6 +5,7 @@ #include #include +#include #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> 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, -- 2.39.5