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

Fix Uninitialized Try exception when co_awaiting on fulfilled futures.

Summary:
FutureAwaitable currently does not properly handle the case where an
already fulfilled future is awaited on. In particular, await_ready() is based
on the value of future_.isReady(), while await_resume() pulls the value from
result_, regardless of whether or not result_ has been correctly initialized by
the callback registered in await_suspend. When an already fulfilled
future is awaited on, await_ready() will return true immediately, and await_suspend() will
be bypassed and await_resume() called immediately, throwing an exception since result_ hasn't been initialized.

Reviewed By: lewissbaker

Differential Revision: D12816274

fbshipit-source-id: f5f697e433c1621f829af6f5509d08bac2229ddb
parent d2c2e40c
......@@ -321,4 +321,15 @@ TEST(Coro, Baton) {
EXPECT_EQ(42, std::move(future).get());
}
coro::Task<int> taskFuture(int value) {
co_return co_await folly::makeFuture<int>(std::move(value));
}
TEST(Coro, FulfilledFuture) {
ManualExecutor executor;
auto value =
taskFuture(42).scheduleOn(&executor).start().via(&executor).getVia(
&executor);
EXPECT_EQ(42, value);
}
#endif
......@@ -2053,18 +2053,17 @@ class FutureAwaitable {
}
T await_resume() {
return std::move(result_).value();
return std::move(future_).value();
}
void await_suspend(std::experimental::coroutine_handle<> h) {
future_.setCallback_([this, h](Try<T>&& result) mutable {
result_ = std::move(result);
future_.setCallback_([h](Try<T>&&) mutable {
// Don't std::move() so the try is left in the future for await_resume()
h.resume();
});
}
private:
folly::Try<T> result_;
folly::Future<T> future_;
};
......
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