]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/common/interruptible_future: check for interruptions after the
authorXuehan Xu <xuxuehan@qianxin.com>
Wed, 11 Mar 2026 08:02:19 +0000 (16:02 +0800)
committerXuehan Xu <xuxuehan@qianxin.com>
Wed, 11 Mar 2026 08:05:51 +0000 (16:05 +0800)
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 <xuxuehan@qianxin.com>
src/crimson/common/interruptible_future.h

index bd8fec5a07e104c6084c8e03d6912a0348daca71..c1663d512788b9b3db5a0a4024ab1da2c098775b 100644 (file)
@@ -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<InterruptCond>.interrupt_cond;
-      INTR_FUT_DEBUG(
-       "interruptible_future_detail::get() waiting, interrupt_cond: {},{}",
-       (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
-       typeid(InterruptCond).name());
-      interrupt_cond<InterruptCond>.reset();
-      try {
-       auto&& value = core_type::get();
-       interrupt_cond<InterruptCond>.set(interruption_condition);
-       INTR_FUT_DEBUG(
-         "interruptible_future_detail::get() got, interrupt_cond: {},{}",
-         (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
-         typeid(InterruptCond).name());
-       return std::move(value);
-      } catch (std::exception &e) {
-       interrupt_cond<InterruptCond>.set(interruption_condition);
-       INTR_FUT_DEBUG(
-         "interruptible_future_detail::get() error {}, interrupt_cond: {},{}",
-         e,
-         (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
-         typeid(InterruptCond).name());
-        throw;
+    }
+    // destined to wait!
+    auto interruption_condition = interrupt_cond<InterruptCond>.interrupt_cond;
+    INTR_FUT_DEBUG(
+      "interruptible_future_detail::get() waiting, interrupt_cond: {},{}",
+      (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
+      typeid(InterruptCond).name());
+    interrupt_cond<InterruptCond>.reset();
+    try {
+      auto&& value = core_type::get();
+      auto ifut = interruption_condition->template may_interrupt<seastar::future<>>();
+      if (ifut) {
+        std::rethrow_exception(ifut->get_exception());
       }
+
+      interrupt_cond<InterruptCond>.set(interruption_condition);
+      INTR_FUT_DEBUG(
+        "interruptible_future_detail::get() got, interrupt_cond: {},{}",
+        (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
+        typeid(InterruptCond).name());
+      return std::move(value);
+    } catch (std::exception &e) {
+      interrupt_cond<InterruptCond>.set(interruption_condition);
+      INTR_FUT_DEBUG(
+        "interruptible_future_detail::get() error {}, interrupt_cond: {},{}",
+        e,
+        (void*)interrupt_cond<InterruptCond>.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<InterruptCond>.interrupt_cond;
+    }
+    // destined to wait!
+    auto interruption_condition = interrupt_cond<InterruptCond>.interrupt_cond;
+    INTR_FUT_DEBUG(
+      "green_get() waiting, interrupt_cond: {},{}",
+      (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
+      typeid(InterruptCond).name());
+    interrupt_cond<InterruptCond>.reset();
+    try {
+      auto&& value = fut.get();
+      auto ifut = interruption_condition->template may_interrupt<future<void>>();
+      if (ifut) {
+        std::rethrow_exception(ifut->get_exception());
+      }
+      interrupt_cond<InterruptCond>.set(interruption_condition);
       INTR_FUT_DEBUG(
-        "green_get() waiting, interrupt_cond: {},{}",
+        "green_get() got, interrupt_cond: {},{}",
         (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
         typeid(InterruptCond).name());
-      interrupt_cond<InterruptCond>.reset();
-      try {
-       auto&& value = fut.get();
-       interrupt_cond<InterruptCond>.set(interruption_condition);
-       INTR_FUT_DEBUG(
-         "green_get() got, interrupt_cond: {},{}",
-         (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
-         typeid(InterruptCond).name());
-       return std::move(value);
-      } catch (std::exception &e) {
-       interrupt_cond<InterruptCond>.set(interruption_condition);
-       INTR_FUT_DEBUG(
-         "green_get() error {}, interrupt_cond: {},{}",
-         e,
-         (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
-         typeid(InterruptCond).name());
-        throw;
-      }
+      return std::move(value);
+    } catch (std::exception &e) {
+      interrupt_cond<InterruptCond>.set(interruption_condition);
+      INTR_FUT_DEBUG(
+        "green_get() error {}, interrupt_cond: {},{}",
+        e,
+        (void*)interrupt_cond<InterruptCond>.interrupt_cond.get(),
+        typeid(InterruptCond).name());
+      throw;
     }
   }
 
@@ -1575,6 +1582,11 @@ public:
        typeid(InterruptCond).name());
       throw;
     }
+    auto &interrupt_condition = *interrupt_cond<InterruptCond>.interrupt_cond;
+    auto fut = interrupt_condition.template may_interrupt<future<void>>();
+    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<InterruptCond>.interrupt_cond;
+      auto fut = interrupt_condition.template may_interrupt<future<void>>();
+      if (fut) {
+        std::rethrow_exception(fut->get_exception());
+      }
     }
   }
 };