Commit 1b24cbe4 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Disable exception checks if it wasn't thrown by a fiber

Summary: If fiber was activated with an exception it's safe for that fiber to be preempted.

Differential Revision: D15640534

fbshipit-source-id: d908aacd81e1ec57874324a58b180587a1fe2eeb
parent dff7ae96
...@@ -174,8 +174,10 @@ void Fiber::preempt(State state) { ...@@ -174,8 +174,10 @@ void Fiber::preempt(State state) {
DCHECK_EQ(fiberManager_.activeFiber_, this); DCHECK_EQ(fiberManager_.activeFiber_, this);
DCHECK_EQ(state_, RUNNING); DCHECK_EQ(state_, RUNNING);
DCHECK_NE(state, RUNNING); DCHECK_NE(state, RUNNING);
CHECK(state == AWAITING_IMMEDIATE || !std::current_exception()); if (state != AWAITING_IMMEDIATE) {
CHECK(state == AWAITING_IMMEDIATE || !std::uncaught_exception()); CHECK(fiberManager_.currentException_ == std::current_exception());
CHECK_EQ(fiberManager_.numUncaughtExceptions_, uncaught_exceptions());
}
state_ = state; state_ = state;
......
...@@ -198,6 +198,9 @@ void FiberManager::runFibersHelper(LoopFunc&& loopFunc) { ...@@ -198,6 +198,9 @@ void FiberManager::runFibersHelper(LoopFunc&& loopFunc) {
// Support nested FiberManagers // Support nested FiberManagers
auto originalFiberManager = std::exchange(currentFiberManager_, this); auto originalFiberManager = std::exchange(currentFiberManager_, this);
numUncaughtExceptions_ = uncaught_exceptions();
currentException_ = std::current_exception();
// Save current context, and reset it after executing all fibers. // Save current context, and reset it after executing all fibers.
// This can avoid a lot of context swapping, // This can avoid a lot of context swapping,
// if the Fibers share the same context // if the Fibers share the same context
......
...@@ -548,6 +548,15 @@ class FiberManager : public ::folly::Executor { ...@@ -548,6 +548,15 @@ class FiberManager : public ::folly::Executor {
ssize_t remoteCount_{0}; ssize_t remoteCount_{0};
/**
* Number of uncaught exceptions when FiberManager loop was called.
*/
ssize_t numUncaughtExceptions_{0};
/**
* Current exception when FiberManager loop was called.
*/
std::exception_ptr currentException_;
class FibersPoolResizer final : private HHWheelTimer::Callback { class FibersPoolResizer final : private HHWheelTimer::Callback {
public: public:
explicit FibersPoolResizer(FiberManager& fm) : fiberManager_(fm) {} explicit FibersPoolResizer(FiberManager& fm) : fiberManager_(fm) {}
......
...@@ -2460,3 +2460,57 @@ TEST(FiberManager, swapWithException) { ...@@ -2460,3 +2460,57 @@ TEST(FiberManager, swapWithException) {
}); });
evb.loop(); evb.loop();
} }
TEST(FiberManager, loopInCatch) {
folly::EventBase evb;
auto& fm = getFiberManager(evb);
bool started = false;
folly::fibers::Baton baton;
bool done = false;
fm.addTask([&] {
started = true;
baton.wait();
done = true;
});
try {
throw std::logic_error("expected");
} catch (...) {
EXPECT_FALSE(started);
evb.drive();
EXPECT_TRUE(started);
EXPECT_FALSE(done);
baton.post();
evb.drive();
EXPECT_TRUE(done);
}
}
TEST(FiberManager, loopInUnwind) {
folly::EventBase evb;
auto& fm = getFiberManager(evb);
bool started = false;
folly::fibers::Baton baton;
bool done = false;
fm.addTask([&] {
started = true;
baton.wait();
done = true;
});
try {
SCOPE_EXIT {
EXPECT_FALSE(started);
evb.drive();
EXPECT_TRUE(started);
EXPECT_FALSE(done);
baton.post();
evb.drive();
EXPECT_TRUE(done);
};
throw std::logic_error("expected");
} catch (...) {
}
}
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