Commit ca0f799d authored by Jason Rahman's avatar Jason Rahman Committed by Facebook Github Bot

Correctly propagate cancellations through within()

Summary:
Within() is not properly propegating cancellations and other
interrupts via raise() since it technically breaks the normal propegation
mechnaism of copying the interrupt handler pointer.

Reviewed By: yfeldblum

Differential Revision: D6838285

fbshipit-source-id: 8f3efbd3eebe21c2f348b6aba991b0997be4f14f
parent 65215eed
......@@ -1314,6 +1314,14 @@ Future<T> Future<T>::within(Duration dur, E e, Timekeeper* tk) {
}
});
// Properly propagate interrupt values through futures chained after within()
ctx->promise.setInterruptHandler(
[weakCtx = to_weak_ptr(ctx)](const exception_wrapper& ex) {
if (auto lockedCtx = weakCtx.lock()) {
lockedCtx->thisFuture.raise(ex);
}
});
// Have time keeper use a weak ptr to hold ctx,
// so that ctx can be deallocated as soon as the future job finished.
tk->after(dur).then([weakCtx = to_weak_ptr(ctx)](Try<Unit> const& t) mutable {
......
......@@ -195,6 +195,21 @@ TEST(Timekeeper, chainedInterruptTest) {
EXPECT_FALSE(test);
}
TEST(Timekeeper, withinChainedInterruptTest) {
bool test = false;
Promise<Unit> p;
p.setInterruptHandler([&test, &p](const exception_wrapper& ex) {
ex.handle(
[&test](const FutureCancellation& /* cancellation */) { test = true; });
p.setException(ex);
});
auto f = p.getFuture().within(milliseconds(100));
EXPECT_FALSE(test) << "Sanity check";
f.cancel();
f.wait();
EXPECT_TRUE(test);
}
TEST(Timekeeper, executor) {
class ExecutorTester : public Executor {
public:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment