From dc9a05c7a308f62d4f0e8d3742aa86370b751624 Mon Sep 17 00:00:00 2001 From: Xuehan Xu Date: Fri, 18 Aug 2023 11:21:03 +0800 Subject: [PATCH] crimson/common/interruptible_future: deal with exceptions thrown from seastar::future::get() and seastar::thread::yield() Signed-off-by: Xuehan Xu --- src/crimson/common/interruptible_future.h | 117 ++++++++++++++++------ 1 file changed, 87 insertions(+), 30 deletions(-) diff --git a/src/crimson/common/interruptible_future.h b/src/crimson/common/interruptible_future.h index cac6f65d1fd..6ed11088e1a 100644 --- a/src/crimson/common/interruptible_future.h +++ b/src/crimson/common/interruptible_future.h @@ -307,10 +307,17 @@ Result non_futurized_call_with_interruption( return std::forward(err); } } catch (std::exception& e) { + INTR_FUT_DEBUG( + "non_futurized_call_with_interruption catched exception: {}, " + "interrupt_condition: {}, interrupt_cond: {},{}", + e, + (void*)interrupt_condition.get(), + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); // Clear the global "interrupt_cond" to prevent it from interfering other // continuation chains. interrupt_cond.reset(); - throw e; + std::throw_with_nested(std::runtime_error("failed to run interruptible continuation")); } } @@ -421,13 +428,25 @@ public: (void*)interrupt_cond.interrupt_cond.get(), typeid(InterruptCond).name()); interrupt_cond.reset(); - 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); + 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()); + std::throw_with_nested( + std::runtime_error( + "failed to run interruptible continuation")); + } } } @@ -1113,11 +1132,13 @@ public: typename... Params> static inline auto with_interruption_cond( OpFunc&& opfunc, OnInterrupt&& efunc, InterruptCond &&cond, Params&&... params) { + auto ic = seastar::make_lw_shared(std::move(cond)); INTR_FUT_DEBUG( - "with_interruption_cond: interrupt_cond: {}", - (void*)interrupt_cond.interrupt_cond.get()); + "with_interruption_cond: interrupt_cond: {}, ic: {}", + (void*)interrupt_cond.interrupt_cond.get(), + (void*)ic.get()); return internal::call_with_interruption_impl( - seastar::make_lw_shared(std::move(cond)), + std::move(ic), std::forward(opfunc), std::forward(params)... ).template handle_interruption(std::move(efunc)); @@ -1431,13 +1452,25 @@ public: (void*)interrupt_cond.interrupt_cond.get(), typeid(InterruptCond).name()); interrupt_cond.reset(); - 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); + 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()); + std::throw_with_nested( + std::runtime_error( + "failed to run interruptible continuation")); + } } } @@ -1450,12 +1483,24 @@ public: (void*)interruption_condition.get(), typeid(InterruptCond).name()); interrupt_cond.reset(); - seastar::thread::yield(); - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "interruptible_future_detail::yield() yield back, interrupt_cond: {},{}", - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); + try { + seastar::thread::yield(); + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::yield() yield back, interrupt_cond: {},{}", + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + } catch (std::exception &e) { + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::yield() error {}, interrupt_cond: {},{}", + e, + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + std::throw_with_nested( + std::runtime_error( + "failed to run interruptible continuation")); + } } static void maybe_yield() { @@ -1468,12 +1513,24 @@ public: (void*)interruption_condition.get(), typeid(InterruptCond).name()); interrupt_cond.reset(); - seastar::thread::yield(); - interrupt_cond.set(interruption_condition); - INTR_FUT_DEBUG( - "interruptible_future_detail::may_yield() yield back, interrupt_cond: {},{}", - (void*)interrupt_cond.interrupt_cond.get(), - typeid(InterruptCond).name()); + try { + seastar::thread::yield(); + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::may_yield() yield back, interrupt_cond: {},{}", + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + } catch (std::exception &e) { + interrupt_cond.set(interruption_condition); + INTR_FUT_DEBUG( + "interruptible_future_detail::may_yield() error {}, interrupt_cond: {},{}", + e, + (void*)interrupt_cond.interrupt_cond.get(), + typeid(InterruptCond).name()); + std::throw_with_nested( + std::runtime_error( + "failed to run interruptible continuation")); + } } } }; -- 2.39.5