Commit 19910c37 authored by Nick Cooper's avatar Nick Cooper Committed by Facebook Github Bot

folly::coro::blockingWait should gracefully handle cases with thrown exceptions

Summary:
If the waited upon object throws an exception when blockingWait is called within a fiber context this can cause a SIGABT as it is not permissible to yield (due to the inner baton) in an exception context.

To fix this, instead capture the exception and permit destruction to occur outside of exception handling.

Reviewed By: andriigrynenko

Differential Revision: D19951124

fbshipit-source-id: cf1bf9a62557147863390132f551d08e20c02c2d
parent c9e346af
...@@ -386,8 +386,16 @@ template < ...@@ -386,8 +386,16 @@ template <
std::enable_if_t<!is_awaitable_v<SemiAwaitable>, int> = 0> std::enable_if_t<!is_awaitable_v<SemiAwaitable>, int> = 0>
auto blockingWait(SemiAwaitable&& awaitable) auto blockingWait(SemiAwaitable&& awaitable)
-> detail::decay_rvalue_reference_t<semi_await_result_t<SemiAwaitable>> { -> detail::decay_rvalue_reference_t<semi_await_result_t<SemiAwaitable>> {
std::exception_ptr eptr;
{
detail::BlockingWaitExecutor executor; detail::BlockingWaitExecutor executor;
try {
return blockingWait(static_cast<SemiAwaitable&&>(awaitable), &executor); return blockingWait(static_cast<SemiAwaitable&&>(awaitable), &executor);
} catch (...) {
eptr = std::current_exception();
}
}
std::rethrow_exception(eptr);
} }
} // namespace coro } // namespace coro
......
...@@ -269,6 +269,24 @@ TEST_F(BlockingWaitTest, WaitTaskInFiber) { ...@@ -269,6 +269,24 @@ TEST_F(BlockingWaitTest, WaitTaskInFiber) {
EXPECT_EQ(42, std::move(future).get()); EXPECT_EQ(42, std::move(future).get());
} }
struct ExpectedException {};
TEST_F(BlockingWaitTest, WaitTaskInFiberException) {
folly::EventBase evb;
auto& fm = folly::fibers::getFiberManager(evb);
fm.addTask([] {
try {
folly::coro::blockingWait(
folly::coro::co_invoke([&]() -> folly::coro::Task<void> {
folly::via(co_await folly::coro::co_current_executor, []() {});
throw ExpectedException();
}));
} catch (const ExpectedException&) {
}
});
evb.loop();
}
TEST_F(BlockingWaitTest, WaitOnSemiFuture) { TEST_F(BlockingWaitTest, WaitOnSemiFuture) {
int result = folly::coro::blockingWait(folly::makeSemiFuture(123)); int result = folly::coro::blockingWait(folly::makeSemiFuture(123));
CHECK_EQ(result, 123); CHECK_EQ(result, 123);
......
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