From: Xuehan Xu Date: Wed, 11 Mar 2026 08:02:19 +0000 (+0800) Subject: crimson/common/interruptible_future: check for interruptions after the X-Git-Tag: v21.0.1~683^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b2b2cd7520010948440b750ff3ce63c018c0e947;p=ceph.git crimson/common/interruptible_future: check for interruptions after the stack resumes Interruptions may happen when the continuation execution is yielded, through interruptor::green_get/yield/maybe_yield. So we need to check it when the execution resumes, otherwise, interruptions may be leaked Fixes: https://tracker.ceph.com/issues/75333 Signed-off-by: Xuehan Xu --- diff --git a/src/crimson/common/interruptible_future.h b/src/crimson/common/interruptible_future.h index bd8fec5a07e1..c1663d512788 100644 --- a/src/crimson/common/interruptible_future.h +++ b/src/crimson/common/interruptible_future.h @@ -429,31 +429,35 @@ public: value_type&& get() { if (core_type::available()) { return core_type::get(); - } else { - // destined to wait! - auto interruption_condition = interrupt_cond.interrupt_cond; - INTR_FUT_DEBUG( - "interruptible_future_detail::get() waiting, interrupt_cond: {},{}", - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); - interrupt_cond.reset(); - try { - auto&& value = core_type::get(); - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "interruptible_future_detail::get() got, interrupt_cond: {},{}", - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); - return std::move(value); - } catch (std::exception &e) { - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "interruptible_future_detail::get() error {}, interrupt_cond: {},{}", - e, - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); - throw; + } + // destined to wait! + auto interruption_condition = interrupt_cond.interrupt_cond; + INTR_FUT_DEBUG( + "interruptible_future_detail::get() waiting, interrupt_cond: {},{}", + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + interrupt_cond.reset(); + try { + auto&& value = core_type::get(); + auto ifut = interruption_condition->template may_interrupt>(); + if (ifut) { + std::rethrow_exception(ifut->get_exception()); } + + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::get() got, interrupt_cond: {},{}", + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + return std::move(value); + } catch (std::exception &e) { + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::get() error {}, interrupt_cond: {},{}", + e, + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + throw; } } @@ -1522,31 +1526,34 @@ public: static decltype(auto) green_get(FutureT&& fut) { if (fut.available()) { return fut.get(); - } else { - // destined to wait! - auto interruption_condition = interrupt_cond.interrupt_cond; + } + // destined to wait! + auto interruption_condition = interrupt_cond.interrupt_cond; + INTR_FUT_DEBUG( + "green_get() waiting, interrupt_cond: {},{}", + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + interrupt_cond.reset(); + try { + auto&& value = fut.get(); + auto ifut = interruption_condition->template may_interrupt>(); + if (ifut) { + std::rethrow_exception(ifut->get_exception()); + } + interrupt_cond.set(interruption_condition); INTR_FUT_DEBUG( - "green_get() waiting, interrupt_cond: {},{}", + "green_get() got, interrupt_cond: {},{}", (void*)interrupt_cond.interrupt_cond.get(), typeid(InterruptCond).name()); - interrupt_cond.reset(); - try { - auto&& value = fut.get(); - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "green_get() got, interrupt_cond: {},{}", - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); - return std::move(value); - } catch (std::exception &e) { - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "green_get() error {}, interrupt_cond: {},{}", - e, - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); - throw; - } + return std::move(value); + } catch (std::exception &e) { + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "green_get() error {}, interrupt_cond: {},{}", + e, + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + throw; } } @@ -1575,6 +1582,11 @@ public: typeid(InterruptCond).name()); throw; } + auto &interrupt_condition = *interrupt_cond.interrupt_cond; + auto fut = interrupt_condition.template may_interrupt>(); + if (fut) { + std::rethrow_exception(fut->get_exception()); + } } static void maybe_yield() { @@ -1603,6 +1615,11 @@ public: typeid(InterruptCond).name()); throw; } + auto &interrupt_condition = *interrupt_cond.interrupt_cond; + auto fut = interrupt_condition.template may_interrupt>(); + if (fut) { + std::rethrow_exception(fut->get_exception()); + } } } };