Commit bf52653d authored by Mark McDuff's avatar Mark McDuff Committed by Sara Golemon

high init priority for FiberManagerMap data

Summary: Ran into a bug in D2158570 where we dtor'ing these data structures before the event bases destructed, so the assert on line 47 (of the old code) failed.

Reviewed By: @andriigrynenko

Differential Revision: D2198318
parent 28f7b88b
...@@ -23,30 +23,49 @@ ...@@ -23,30 +23,49 @@
namespace folly { namespace fibers { namespace folly { namespace fibers {
namespace detail { namespace {
// Leak these intentionally. During shutdown, we may call getFiberManager, and
// want access to the fiber managers during that time.
class LocalFiberManagerMapTag; class LocalFiberManagerMapTag;
folly::ThreadLocal<std::unordered_map<folly::EventBase*, FiberManager*>, typedef folly::ThreadLocal<
LocalFiberManagerMapTag> localFiberManagerMap; std::unordered_map<folly::EventBase*, FiberManager*>,
std::unordered_map<folly::EventBase*, std::unique_ptr<FiberManager>> LocalFiberManagerMapTag>
fiberManagerMap; LocalMapType;
std::mutex fiberManagerMapMutex; LocalMapType* localFiberManagerMap() {
static auto ret = new LocalMapType();
return ret;
}
typedef
std::unordered_map<folly::EventBase*, std::unique_ptr<FiberManager>>
MapType;
MapType* fiberManagerMap() {
static auto ret = new MapType();
return ret;
}
std::mutex* fiberManagerMapMutex() {
static auto ret = new std::mutex();
return ret;
}
class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback { class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback {
public: public:
explicit OnEventBaseDestructionCallback(folly::EventBase& evb) explicit OnEventBaseDestructionCallback(folly::EventBase& evb)
: evb_(&evb) {} : evb_(&evb) {}
void runLoopCallback() noexcept override { void runLoopCallback() noexcept override {
for (auto& localMap : localFiberManagerMap.accessAllThreads()) { for (auto& localMap : localFiberManagerMap()->accessAllThreads()) {
localMap.erase(evb_); localMap.erase(evb_);
} }
std::unique_ptr<FiberManager> fm; std::unique_ptr<FiberManager> fm;
{ {
std::lock_guard<std::mutex> lg(fiberManagerMapMutex); std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());
auto it = fiberManagerMap.find(evb_); auto it = fiberManagerMap()->find(evb_);
assert(it != fiberManagerMap.end()); assert(it != fiberManagerMap()->end());
fm = std::move(it->second); fm = std::move(it->second);
fiberManagerMap.erase(it); fiberManagerMap()->erase(it);
} }
assert(fm.get() != nullptr); assert(fm.get() != nullptr);
fm->loopUntilNoReady(); fm->loopUntilNoReady();
...@@ -58,10 +77,10 @@ class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback { ...@@ -58,10 +77,10 @@ class OnEventBaseDestructionCallback : public folly::EventBase::LoopCallback {
FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb, FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb,
const FiberManager::Options& opts) { const FiberManager::Options& opts) {
std::lock_guard<std::mutex> lg(fiberManagerMapMutex); std::lock_guard<std::mutex> lg(*fiberManagerMapMutex());
auto it = fiberManagerMap.find(&evb); auto it = fiberManagerMap()->find(&evb);
if (LIKELY(it != fiberManagerMap.end())) { if (LIKELY(it != fiberManagerMap()->end())) {
return it->second.get(); return it->second.get();
} }
...@@ -69,22 +88,22 @@ FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb, ...@@ -69,22 +88,22 @@ FiberManager* getFiberManagerThreadSafe(folly::EventBase& evb,
loopController->attachEventBase(evb); loopController->attachEventBase(evb);
auto fiberManager = auto fiberManager =
folly::make_unique<FiberManager>(std::move(loopController), opts); folly::make_unique<FiberManager>(std::move(loopController), opts);
auto result = fiberManagerMap.emplace(&evb, std::move(fiberManager)); auto result = fiberManagerMap()->emplace(&evb, std::move(fiberManager));
evb.runOnDestruction(new OnEventBaseDestructionCallback(evb)); evb.runOnDestruction(new OnEventBaseDestructionCallback(evb));
return result.first->second.get(); return result.first->second.get();
} }
} // detail namespace } // namespace
FiberManager& getFiberManager(folly::EventBase& evb, FiberManager& getFiberManager(folly::EventBase& evb,
const FiberManager::Options& opts) { const FiberManager::Options& opts) {
auto it = detail::localFiberManagerMap->find(&evb); auto it = (*localFiberManagerMap())->find(&evb);
if (LIKELY(it != detail::localFiberManagerMap->end())) { if (LIKELY(it != (*localFiberManagerMap())->end())) {
return *(it->second); return *(it->second);
} }
auto fm = detail::getFiberManagerThreadSafe(evb, opts); auto fm = getFiberManagerThreadSafe(evb, opts);
detail::localFiberManagerMap->emplace(&evb, fm); (*localFiberManagerMap())->emplace(&evb, fm);
return *fm; return *fm;
} }
......
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