Commit 0f76e090 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot 8

Make outstanding LoopKeepAlive hold EventBase destructor

Summary:
LoopKeepAlive handle can be grabbed to signal that some external event will later be scheduled on the EventBase via runInEventBaseThread. Usually the code which will be calling runInEventBaseThread only has a raw pointer to an EventBase, so it doesn't have any way to know it was destroyed.

This change ensures that EventBase destructor will keep running the event loop until all such LoopKeepAlive handles are released.

Reviewed By: yfeldblum

Differential Revision: D3323835

fbshipit-source-id: 4071dae691a61dfebe2f1759cf99f661b161fa4a
parent f464accb
......@@ -195,6 +195,14 @@ EventBase::EventBase(event_base* evb, bool enableTimeMeasurement)
}
EventBase::~EventBase() {
// Keep looping until all keep-alive handles are released. Each keep-alive
// handle signals that some external code will still schedule some work on
// this EventBase (so it's not safe to destroy it).
while (!loopKeepAlive_.unique()) {
applyLoopKeepAlive();
loopOnce();
}
// Call all destruction callbacks, before we start cleaning up our state.
while (!onDestructionCallbacks_.empty()) {
LoopCallback* callback = &onDestructionCallbacks_.front();
......
......@@ -1736,7 +1736,8 @@ TEST(EventBaseTest, LoopKeepAlive) {
std::thread t([&, loopKeepAlive = evb.loopKeepAlive() ] {
/* sleep override */ std::this_thread::sleep_for(
std::chrono::milliseconds(100));
evb.runInEventBaseThread([&] { done = true; });
evb.runInEventBaseThread(
[&done, loopKeepAlive = std::move(loopKeepAlive) ] { done = true; });
});
evb.loop();
......@@ -1756,7 +1757,8 @@ TEST(EventBaseTest, LoopKeepAliveInLoop) {
t = std::thread([&, loopKeepAlive = evb.loopKeepAlive() ] {
/* sleep override */ std::this_thread::sleep_for(
std::chrono::milliseconds(100));
evb.runInEventBaseThread([&] { done = true; });
evb.runInEventBaseThread(
[&done, loopKeepAlive = std::move(loopKeepAlive) ] { done = true; });
});
});
......@@ -1766,3 +1768,25 @@ TEST(EventBaseTest, LoopKeepAliveInLoop) {
t.join();
}
TEST(EventBaseTest, LoopKeepAliveShutdown) {
auto evb = folly::make_unique<EventBase>();
bool done = false;
std::thread t(
[&done, loopKeepAlive = evb->loopKeepAlive(), evbPtr = evb.get() ] {
/* sleep override */ std::this_thread::sleep_for(
std::chrono::milliseconds(100));
evbPtr->runInEventBaseThread(
[&done, loopKeepAlive = std::move(loopKeepAlive) ] {
done = true;
});
});
evb.reset();
ASSERT_TRUE(done);
t.join();
}
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