Commit e17fce32 authored by Victor Zverovich's avatar Victor Zverovich Committed by Facebook Github Bot

Fix a race on destruction of ScopedEventBaseThread

Summary:
This diff fixes a race that happens on destruction of `ScopedEventBaseThread`.

```
Thread1: ~ScopedEventBaseThread()
Thread1: eb_.terminateLoopSoon() <- preempted just after stop_ = true
Thread2: eb->loopForever() in run(...) exits because stop_ is true
Thread2: ...
Thread2: eb->~EventBase()
Thread1: queue_->putMessage(nullptr) <- accesses destroyed EventBase
```

Reviewed By: yfeldblum

Differential Revision: D5042654

fbshipit-source-id: 95515ed7cde09ff5f125ef121bea86ab3907f98a
parent 9c626faa
...@@ -27,7 +27,11 @@ using namespace std; ...@@ -27,7 +27,11 @@ using namespace std;
namespace folly { namespace folly {
static void run(EventBaseManager* ebm, EventBase* eb, const StringPiece& name) { static void run(
EventBaseManager* ebm,
EventBase* eb,
folly::Baton<>* stop,
const StringPiece& name) {
if (name.size()) { if (name.size()) {
folly::setThreadName(name); folly::setThreadName(name);
} }
...@@ -38,6 +42,8 @@ static void run(EventBaseManager* ebm, EventBase* eb, const StringPiece& name) { ...@@ -38,6 +42,8 @@ static void run(EventBaseManager* ebm, EventBase* eb, const StringPiece& name) {
// must destruct in io thread for on-destruction callbacks // must destruct in io thread for on-destruction callbacks
EventBase::StackFunctionLoopCallback cb([=] { ebm->clearEventBase(); }); EventBase::StackFunctionLoopCallback cb([=] { ebm->clearEventBase(); });
eb->runOnDestruction(&cb); eb->runOnDestruction(&cb);
// wait until terminateLoopSoon() is complete
stop->wait();
eb->~EventBase(); eb->~EventBase();
} }
...@@ -55,12 +61,13 @@ ScopedEventBaseThread::ScopedEventBaseThread( ...@@ -55,12 +61,13 @@ ScopedEventBaseThread::ScopedEventBaseThread(
const StringPiece& name) const StringPiece& name)
: ebm_(ebm ? ebm : EventBaseManager::get()) { : ebm_(ebm ? ebm : EventBaseManager::get()) {
new (&eb_) EventBase(); new (&eb_) EventBase();
th_ = thread(run, ebm_, &eb_, name); th_ = thread(run, ebm_, &eb_, &stop_, name);
eb_.waitUntilRunning(); eb_.waitUntilRunning();
} }
ScopedEventBaseThread::~ScopedEventBaseThread() { ScopedEventBaseThread::~ScopedEventBaseThread() {
eb_.terminateLoopSoon(); eb_.terminateLoopSoon();
stop_.post();
th_.join(); th_.join();
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <folly/Baton.h>
#include <folly/io/async/EventBase.h> #include <folly/io/async/EventBase.h>
namespace folly { namespace folly {
...@@ -65,6 +66,7 @@ class ScopedEventBaseThread { ...@@ -65,6 +66,7 @@ class ScopedEventBaseThread {
mutable EventBase eb_; mutable EventBase eb_;
}; };
std::thread th_; std::thread th_;
folly::Baton<> stop_;
}; };
} }
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