Commit df9437f9 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook GitHub Bot

Fix observer initialization on fiber

Summary: Observer initialization is blocking and is using thread-local state to detect cycles/track dependencies. When running on a fiber we have to make sure the fiber doesn't get suspended during observer initialization.

Reviewed By: yfeldblum

Differential Revision: D28306797

fbshipit-source-id: 807a4553e89f9fa807e6c745a623041dbb0e47ce
parent 4c23632f
......@@ -20,6 +20,7 @@
#include <folly/experimental/observer/detail/Core.h>
#include <folly/experimental/observer/detail/GraphCycleDetector.h>
#include <folly/fibers/FiberManager.h>
#include <folly/futures/Future.h>
#include <folly/synchronization/SanitizeThread.h>
......@@ -92,12 +93,14 @@ class ObserverManager {
auto& instance = getInstance();
auto inManagerThread = std::exchange(inManagerThread_, true);
SCOPE_EXIT { inManagerThread_ = inManagerThread; };
folly::fibers::runInMainContext([&] {
auto inManagerThread = std::exchange(inManagerThread_, true);
SCOPE_EXIT { inManagerThread_ = inManagerThread; };
SharedMutexReadPriority::ReadHolder rh(instance.versionMutex_);
SharedMutexReadPriority::ReadHolder rh(instance.versionMutex_);
core->refresh(instance.version_);
core->refresh(instance.version_);
});
}
static void waitForAllUpdates();
......
......@@ -20,6 +20,8 @@
#include <folly/experimental/observer/Observer.h>
#include <folly/experimental/observer/SimpleObservable.h>
#include <folly/experimental/observer/WithJitter.h>
#include <folly/fibers/FiberManager.h>
#include <folly/fibers/FiberManagerMap.h>
#include <folly/portability/GTest.h>
#include <folly/synchronization/Baton.h>
......@@ -860,3 +862,26 @@ TEST(Observer, MakeObserverUpdatesTracking) {
EXPECT_EQ(i, **hazptrObserverGetLocalSnapshotCheck);
}
}
TEST(Observer, Fibers) {
folly::EventBase evb;
auto& fm = folly::fibers::getFiberManager(evb);
auto f1 = fm.addTaskFuture([] {
auto o = makeObserver([] {
folly::futures::sleep(std::chrono::milliseconds{10}).get();
return 1;
});
EXPECT_EQ(1, **o);
});
auto f2 = fm.addTaskFuture([] {
auto o = makeObserver([] {
folly::futures::sleep(std::chrono::milliseconds{20}).get();
return 2;
});
EXPECT_EQ(2, **o);
});
std::move(f1).getVia(&evb);
std::move(f2).getVia(&evb);
}
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