- 09 Oct, 2018 4 commits
-
-
Wez Furlong authored
Summary: These were failing in the watchman build ``` $ cd build && python fbcode_builder/shell_builder.py > ~/run.sh && bash ~/run.sh Traceback (most recent call last): File "fbcode_builder/shell_builder.py", line 110, in <module> steps = make_steps(builder) File "/home/travis/build/facebook/watchman/build/fbcode_builder/utils.py", line 94, in <lambda> steps_for_spec(builder, config['fbcode_builder_spec'](builder)) File "/home/travis/build/facebook/watchman/build/fbcode_builder/fbcode_builder.py", line 144, in build return [self.setup(), self.diagnostics()] + steps File "fbcode_builder/shell_builder.py", line 61, in setup ).format(ccache_dir=ccache_dir) File "/home/travis/build/facebook/watchman/build/fbcode_builder/shell_quoting.py", line 64, in format (k, shell_quote(v).do_not_use_raw_str) for k, v in kwargs.items() KeyError: u'CC' ``` Reviewed By: snarkmaster fbshipit-source-id: 614723e631a82f277739765a920731c872700c45
-
Giuseppe Ottaviano authored
Summary: Add a simple function to dispatch the `instructions` types based on current CPU (overridable in tests). Reviewed By: luciang Differential Revision: D10244149 fbshipit-source-id: ac0c1ff0d14402fa77c939361398db6122dea728
-
Greg McGary authored
Summary: For determining proper use of `strerror_r` based on available decl, move messy `#if` logic out of `String.cpp` and into buck config. Reviewed By: yfeldblum Differential Revision: D10243924 fbshipit-source-id: 6c10fc43562765c158d13ed74961277b633bb606
-
Joe Loser authored
Summary: - LLVM 7 emits a warning about self-assignment. - Silence the warning by using a static_cast. Pull Request resolved: https://github.com/facebook/folly/pull/945 Reviewed By: Orvid Differential Revision: D10236656 Pulled By: yfeldblum fbshipit-source-id: 43b46563357d89db9e0911b894f8fead0a14d660
-
- 08 Oct, 2018 6 commits
-
-
Greg McGary authored
Summary: Apply fixes that work with new unified headers and remain compatible with old per-API+arch headers. I do this to unclutter the diff that enables unified headers, so that it only contains things that are incompatible with old per-API+arch headers. Reviewed By: yfeldblum Differential Revision: D10225372 fbshipit-source-id: b92cb3ef45cf23f2233c39520236c4531dba715b
-
Dan Melnic authored
Summary: Use `FOLLY_ATTR_WEAK` for the annotate functions. (Note: this ignores all push blocking failures!) Differential Revision: D10234953 fbshipit-source-id: 534cb1d2d7d6053bc000e4c7ae3c6df16fc7a958
-
Wez Furlong authored
Summary: `shell_builder.py` allows running the fbcode_builder logic on the host rather than in a container. It emits a bash script with `set -exo pipefail` configured such that any failing step will cause the script to exit with failure. Refs: https://github.com/facebook/watchman/pull/639 Reviewed By: simpkins Differential Revision: D9552411 fbshipit-source-id: c7835deedf07ea342dcb3de61d576a4fb5439985
-
Petr Lapukhov authored
Summary: As titled, purely for uniformity. Reviewed By: yfeldblum Differential Revision: D10098066 fbshipit-source-id: 12d78fcc60805284d3d85f405475e63a85799041
-
Dmitry Koterov authored
Summary: This adds a missing feature. Nested exceptions are cool, see examples in https://en.cppreference.com/w/cpp/error/rethrow_if_nested (bottom of the page). In short, nested exceptions allow people to add "contextual" information to exceptions. Previously we had to write the `try { ew.throw_exception(); } catch (...) { std::throw_with_nested(xxx); }` boilerplate if we used an exception_wrapper (e.g. in futures-oriented code); with this diff, we're able to just run `ew.throw_with_nested(xxx)`. Reviewed By: yfeldblum Differential Revision: D10219994 fbshipit-source-id: cdf0fbe8e4608f6c87d326631e8ffb4919c20711
-
Joe Loser authored
Summary: Pull Request resolved: https://github.com/facebook/folly/pull/944 Reviewed By: Orvid Differential Revision: D10231693 Pulled By: yfeldblum fbshipit-source-id: 9c0c5d7c4c1e4d9d9860c71e608e47d661a41fdd
-
- 07 Oct, 2018 2 commits
-
-
Mark Williams authored
Summary: icc accepts the syntax, but doesn't emit the definition into the object file. Reviewed By: ricklavoie, yfeldblum Differential Revision: D10228495 fbshipit-source-id: 73c1676deb4963a9c30886414cc1722d44a79214
-
Lee Howes authored
Summary: Remove falls to Future::then that take a nullary lambda. This is deprecated and will be deleted. This change replaces them with thenValue([](auto&&){...}) or similar. This does not replace all calls to then with thenValue - other forms will be replaced when those forms of then are due for deletion. Reviewed By: yfeldblum Differential Revision: D10219070 fbshipit-source-id: 13b6f64ee2d7c8741537fe1131bdf3b251361413
-
- 06 Oct, 2018 1 commit
-
-
Philip Pronin authored
Summary: Similar to `--dynamic_cputhreadpoolexecutor`, this is a temporary kill switch until all outstanding issues are addressed that would allow us to use dynamic thread pools unconditionally. Reviewed By: djwatson Differential Revision: D10231230 fbshipit-source-id: b0abd77ff2a6a7ce31727e14eca799a6f3b5535a
-
- 05 Oct, 2018 1 commit
-
-
Aaryaman Sagar authored
Summary: There were some read-modify-write operations that were behaving as read and then modify. This is incorrect when you use DeterministicAtomic without a backing schedule. This is okay if the test is operating in the presence of a DeterministicSchedule schedule, but is probably worth fixing anyway. If using DeterministicAtomic without a backing schedule is considered a bug, we can add an assertion in beforeSharedAccess() and afterSharedAccess() so users know not to try that Reviewed By: djwatson, nbronson Differential Revision: D10190682 fbshipit-source-id: 6a3173d904a40bbc5c96b934a76aff90a48c8608
-
- 04 Oct, 2018 11 commits
-
-
Mark Williams authored
Summary: icc gets confused on the parameter unpacking otherwise. https://godbolt.org/z/rSRZYn Reviewed By: yfeldblum Differential Revision: D10147211 fbshipit-source-id: 85de581ffa4c487523a5e9f173636f74863a82ac
-
Mark Williams authored
Summary: When they come before the explicit instantiations of Rob, icc fails to compile certain combintions of calls. Reviewed By: alexeyt Differential Revision: D10144943 fbshipit-source-id: ce63a4d289f64d1d644b116ab99b45b9da013162
-
Kenny Yu authored
Summary: `folly::SharedMutex` allows `unlock_shared()` to be called in a different thread from the one that locked it There are some places in folly that use this property. Example: In `ObserverManager`, the calling thread 1. acquires the read lock 2. then it schedules some async work and gives ownership of the lock guard to the lambda 3. the thread that performs the async work will unlock the mutex However, this causes false positives for TSAN. It looks like this breaks TSAN's assumptions that a read-write mutex is always read locked and unlocked in the same thread. In the example above, TSAN thinks the calling thread in step (1) still owns the mutex, even though semantically the mutex is now owned by the thread in step (3). This results in false positives for running unit tests with an annotated version of `folly::SharedMutex`. TSAN reports a lock inversion between the `folly::Singleton vaule_.state_` mutex, and the read lock referenced in `ObserverManager`. To suppress this error, this change annotates ObserverManager to let TSAN know that the the thread in step 1 has dropped the lock, and the thread in step 3 now owns the lock. Reviewed By: andriigrynenko Differential Revision: D9797937 fbshipit-source-id: c0e5277bb9cb2f404df8abd3c3d6ea4a16460c78
-
Kenny Yu authored
Summary: TSAN flagged the following lock inversion below. The reason for this lock inversion is because of the following example usage: 1. set request context B, save old one A (lock B, lock A) 2. later on, reset request context back to A, get the old one back B (lock A, lock B) In the two calls, we always locked the the new context first, resulting in a lock inversion. The fix is to always acquire them in a consistent order using `folly::acquireLocked` TSAN report: ``` WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=1574307) Cycle in lock order graph: M159 (0x7b1400000138) => M157 (0x7b14000000e8) => M159 Mutex M157 acquired here while holding mutex M159 in main thread: #0 0x48f18c in AnnotateRWLockAcquired ??:? #1 0x315495 in folly::SharedMutexImpl<false, void, std::atomic, false>::lock_shared() ./folly/SharedMutex.h:385 #2 0x1b0eb8 in folly::detail::LockTraitsImpl<folly::SharedMutexImpl<false, void, std::atomic, false>, (folly::detail::MutexLevel)1, false>::lock_shared(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:157 #3 0x1b0e68 in std::integral_constant<bool, true> folly::LockPolicyShared::lock<folly::SharedMutexImpl<false, void, std::atomic, false> >(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:493 #4 0x1d63a9 in LockedPtrBase ./folly/Synchronized.h:1026 #5 0x1d6258 in LockedPtr ./folly/Synchronized.h:1326 #6 0x1c9a17 in folly::SynchronizedBase<folly::Synchronized<folly::RequestContext::State, folly::SharedMutexImpl<false, void, std::atomic, false> >, (folly::detail::MutexLevel)1>::rlock() const ./folly/Synchronized.h:123 #7 0x1c7530 in folly::RequestContext::setContext(std::shared_ptr<folly::RequestContext>) ./folly/io/async/Request.cpp:243 #8 0x36a7b in folly::RequestContext::create() ./folly/io/async/Request.h:119 #9 0x34916 in RequestContextScopeGuard ./folly/io/async/Request.h:269 Mutex M159 previously acquired by the same thread here: #0 0x48f18c in AnnotateRWLockAcquired ??:? #1 0x315495 in folly::SharedMutexImpl<false, void, std::atomic, false>::lock_shared() ./folly/SharedMutex.h:385 #2 0x1b0eb8 in folly::detail::LockTraitsImpl<folly::SharedMutexImpl<false, void, std::atomic, false>, (folly::detail::MutexLevel)1, false>::lock_shared(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:157 #3 0x1b0e68 in std::integral_constant<bool, true> folly::LockPolicyShared::lock<folly::SharedMutexImpl<false, void, std::atomic, false> >(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:493 #4 0x1d63a9 in LockedPtrBase ./folly/Synchronized.h:1026 #5 0x1d6258 in LockedPtr ./folly/Synchronized.h:1326 #6 0x1c9a17 in folly::SynchronizedBase<folly::Synchronized<folly::RequestContext::State, folly::SharedMutexImpl<false, void, std::atomic, false> >, (folly::detail::MutexLevel)1>::rlock() const ./folly/Synchronized.h:123 #7 0x1c7516 in folly::RequestContext::setContext(std::shared_ptr<folly::RequestContext>) ./folly/io/async/Request.cpp:242 #8 0x36a7b in folly::RequestContext::create() ./folly/io/async/Request.h:119 #9 0x34916 in RequestContextScopeGuard ./folly/io/async/Request.h:269 Mutex M159 acquired here while holding mutex M157 in main thread: #0 0x48f18c in AnnotateRWLockAcquired ??:? #1 0x315495 in folly::SharedMutexImpl<false, void, std::atomic, false>::lock_shared() ./folly/SharedMutex.h:385 #2 0x1b0eb8 in folly::detail::LockTraitsImpl<folly::SharedMutexImpl<false, void, std::atomic, false>, (folly::detail::MutexLevel)1, false>::lock_shared(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:157 #3 0x1b0e68 in std::integral_constant<bool, true> folly::LockPolicyShared::lock<folly::SharedMutexImpl<false, void, std::atomic, false> >(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:493 #4 0x1d63a9 in LockedPtrBase ./folly/Synchronized.h:1026 #5 0x1d6258 in LockedPtr ./folly/Synchronized.h:1326 #6 0x1c9a17 in folly::SynchronizedBase<folly::Synchronized<folly::RequestContext::State, folly::SharedMutexImpl<false, void, std::atomic, false> >, (folly::detail::MutexLevel)1>::rlock() const ./folly/Synchronized.h:123 #7 0x1c7530 in folly::RequestContext::setContext(std::shared_ptr<folly::RequestContext>) ./folly/io/async/Request.cpp:243 #8 0x34b99 in ~RequestContextScopeGuard ./folly/io/async/Request.h:278 Mutex M157 previously acquired by the same thread here: #0 0x48f18c in AnnotateRWLockAcquired ??:? #1 0x315495 in folly::SharedMutexImpl<false, void, std::atomic, false>::lock_shared() ./folly/SharedMutex.h:385 #2 0x1b0eb8 in folly::detail::LockTraitsImpl<folly::SharedMutexImpl<false, void, std::atomic, false>, (folly::detail::MutexLevel)1, false>::lock_shared(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:157 #3 0x1b0e68 in std::integral_constant<bool, true> folly::LockPolicyShared::lock<folly::SharedMutexImpl<false, void, std::atomic, false> >(folly::SharedMutexImpl<false, void, std::atomic, false>&) ./folly/LockTraits.h:493 #4 0x1d63a9 in LockedPtrBase ./folly/Synchronized.h:1026 #5 0x1d6258 in LockedPtr ./folly/Synchronized.h:1326 #6 0x1c9a17 in folly::SynchronizedBase<folly::Synchronized<folly::RequestContext::State, folly::SharedMutexImpl<false, void, std::atomic, false> >, (folly::detail::MutexLevel)1>::rlock() const ./folly/Synchronized.h:123 #7 0x1c7516 in folly::RequestContext::setContext(std::shared_ptr<folly::RequestContext>) ./folly/io/async/Request.cpp:242 #8 0x34b99 in ~RequestContextScopeGuard ./folly/io/async/Request.h:278 ``` Reviewed By: igorsugak Differential Revision: D9797715 fbshipit-source-id: a0f991ae0ec8f3e9d33af6e05db49eceaf3a5174
-
Kenny Yu authored
Summary: There is a lock inversion between VirtualEventBase and the fibers library: 1. During program shutdown, `GlobalCache::getImpl` acquires its `mutex_`, then it calls `VirtualEventBase::runOnDestruction` which acquires the SharedMutex on `onDestructionCallbacks_` 2. During normal program execution, `VirtualEventBase::destroyImpl()` acquires the `onDestructionCallbacks_` lock and then invokes the user-supplied callbacks, which will invoke `GlobalCache::eraseImpl` and acquire `mutex_` The reason for this lock inversion is because in step 2, we are holding a mutex while invoking user-supplied callbacks. The fix is to NOT hold the lock while we invoke these callbacks. Reviewed By: andriigrynenko Differential Revision: D9797816 fbshipit-source-id: 861a915f22138f0c8d3f8bca4d7bf4b9a0aa3d26
-
Kenny Yu authored
Summary: When running tests with a TSAN-annotated version of folly::SharedMutex, I discovered at least 3 types of lock inversions in folly::Singleton code. These inversions are probably benign and deadlock is not possible, but we need to suppress these inversions to prevent too much noise from TSAN. Lock inversions: 1. The users can supply arbitrary create() functions for Singletons. If the create() function happens to acquire a mutex, then this introduces a lock ordering from SingletonVault -> mutex. Later on, when the user code runs in normal operations, we might hold the mutex and try to create a singleton, resulting in the mutex -> SingletonVault ordering 2. SingletonVault::destroyInstances() holds a mutex, and then invokes the user-supplied destroy() functions. In the user supplied destroy functions, we might attempt to create a singleton and acquire the lock in SingletonHolder, resulting in SingletonVault -> SingletonHolder lock ordering. In normal operations, whenever a singleton is created, we have the SingletonHolder -> SingletonVault lock ordering in createInstance() 3. doEagerInit() holds the eagerInitSingleton mutex and then acquires the SingletonVault lock during createInstance(). addEagerInitSingleton() holds the SingletonVault lock and then acquires the eagerInitSingleton lock. The source of these errors is that we are invoking user-supplied callbacks while holding mutexes. However, these lock inversions cannot actually deadlock based on higher-level knowledge of folly::Singleton state transitions. To suppress these errors, use the new `folly::SharedMutexSuppressTSAN` mutex instead, which will not be annotated by TSAN. If we are not building with TSAN, then this mutex is equivalent to a normal `folly::SharedMutex`. Reviewed By: andriigrynenko Differential Revision: D9797988 fbshipit-source-id: 82b5850fe189f7d1dcaca0e3562fabcfafd0cef5
-
Kenny Yu authored
Summary: This diff adds TSAN annotations to `folly::SharedMutex` to allow TSAN to find lock inversions with this type of mutex. Note that only the WritePriority version is annotated, and the ReadPriority version is not. See the comments in the source code for an explanation of this. Some notes about how the annotation was done: - We always call the RELEASED annotations at the beginning of unlock(), and the ACQUIRED annotations at the end of lock(). This prevents a double locking interleaving where thread 1 has unlocked it and before RELEASED is called, another thread has locked it and calls ACQUIRED first. - These annotations treat upgrade locks as equivalent to a shared lock. This prevents any false positives, and keeps the annotations simple. - We need to keep the constructor for SharedMutex as `constexpr` to avoid static initialization bugs. As a result, we need to lazily annotate creation of the mutex. To do this, this adds an extra bit to the `SharedMutex` state to keep track if initialization has been called. In TSAN builds, we have an array of mutexes to enforce that initialization is called at most once. - This diff introduces a new template param AnnotateForThreadSanitizer (default is False). This allows users to use a new folly::SharedMutexSuppressTSAN version to avoid lock inversion detection if there are noisy lock inversions. However, this should be the exception and not the norm. In normal build modes, this is equivalent to a normal SharedMutex. Reviewed By: nbronson Differential Revision: D9677058 fbshipit-source-id: b0f5719a75024937fb81672435fb1c9802f255d7
-
Kenny Yu authored
Summary: This change is part of a bigger effort to make `folly::SharedMutex` compatible with TSAN so that TSAN can find lock inversions with these types of mutexes. In order to do this, we need to annotate the mutex function calls accordingly. The annotation functions are provided by the TSAN runtime library. Upcoming changes to `folly::SharedMutex`: 1. provide annotation helper macros (this change) 2. fix or suppress known issues in existing libraries (these macros will allow us to suppress issues) 3. once all the issues are fixed, annotate `SharedMutex` accordingly Reviewed By: nbronson Differential Revision: D9797582 fbshipit-source-id: 12306db98505fe31a8d8590113d10585840fbe6d
-
Nick Terrell authored
Summary: `AccessSpreader::cachedCurrent()` caches the result of `AccessSpreader::getcpuFunc()` for 32 calls in a thread-local. The cached function takes 2 ns, where the current call takes 12 ns. This comes at the cost of being imprecise when threads migrate to a new cpu. I chose 32 as the number of calls because it only has a 10% overhead over never refreshing (2.05 ns vs 1.83 ns), where 16 has a 30% overhead, and it performs just as well as 64. Reviewed By: ot Differential Revision: D10151009 fbshipit-source-id: 07ed292dfdcdcedcb74c24279f7773a80ad09348
-
Nick Terrell authored
Summary: * The atomic load was being optimized out of the benchmark. * The initializer wasn't being called for the test tags, so `AccessSpreader<ThreadLocalTag>::current()` and `AccessSpreader<PthreadSelfTag>::current()` were always returning 0. Reviewed By: ot Differential Revision: D10154155 fbshipit-source-id: 76be9865c9ee591d24aedc64e6faf4fd24350282
-
Neel Goyal authored
Summary: ALPN is the preferred way to do this. We should only use that and not provide NPN support anymore. Reviewed By: knekritz Differential Revision: D10110626 fbshipit-source-id: 5ec91fe51252bed0a8d8047e481df76a395e1286
-
- 03 Oct, 2018 1 commit
-
-
Saif Hasan authored
Summary: Two things - Use thenValue instead of then in one specific occurrence as later one has been deprecated - Build googletest on `release-1.8.1` as it is the one that compiles with c++11 Reviewed By: cenzhao Differential Revision: D10178139 fbshipit-source-id: 069578716e5e55ef0a25ea87e9ef5ceded1ff9d6
-
- 02 Oct, 2018 2 commits
-
-
Wez Furlong authored
Summary: There's no need for this to be inheritable Reviewed By: yfeldblum Differential Revision: D10139559 fbshipit-source-id: ae2db0d13e33c383fd73c0563b127e62e54a7094
-
Dan Melnic authored
Summary: Add IOBuf::takeOwnershipIov method Reviewed By: yfeldblum, djwatson Differential Revision: D10135962 fbshipit-source-id: 86a22d73aa1b72645640cf026d2dc2f38b02989c
-
- 01 Oct, 2018 4 commits
-
-
Amol Bhave authored
Summary: Use heterogenous lookup for dynamic::getDefault for StringPiece/dynamic keys. Reviewed By: shixiao Differential Revision: D10127452 fbshipit-source-id: 3cf28a28373211428ac5352136cf073e6c377b16
-
Amol Bhave authored
Summary: dynamic::setDefault already calls heterogenous `emplace(...)`, however it does not behave correctly for static constexpr strings. Add a specialization for StringPiece which solves this. The current set of tests does not invoke setDefault with an object as a key. This diffs adds a test that does that. Reviewed By: shixiao Differential Revision: D10007262 fbshipit-source-id: 386a44bf6b0a24f81e843695d177d85b280b907d
-
Nathan Bronson authored
Summary: Document that insert may evaluate its arguments after rehashing. Reviewed By: shixiao Differential Revision: D10132409 fbshipit-source-id: ba5996a309ae201ae08808272edd1fb0b981cc64
-
Petr Lapukhov authored
Summary: Consume `folly::dynamic` and if it matches JSON patch format, build a sequence of patch operations. Application is to be done separately, e.g. by a method of `folly::dynamic` by walking the operations vector (obtained after parsing the patch) and applying operations to the document. This mimics the approach we used previously with `folly::json_pointer`. Reviewed By: yfeldblum Differential Revision: D10017234 fbshipit-source-id: 1d0b9f0967e528b81abf7998c88abdaf70a2fce8
-
- 30 Sep, 2018 4 commits
-
-
Mark Williams authored
Summary: There are no other methods, and icc gets confused otherwise Reviewed By: yfeldblum Differential Revision: D10116562 fbshipit-source-id: 7664501b910e5857e32337d3583dcc948caddd5d
-
Mark Williams authored
Summary: icc doesn't support it. Reviewed By: yfeldblum Differential Revision: D10116547 fbshipit-source-id: 1ed522bd373ab30507f713d855ef02027ce90a91
-
Alexander Zhavnerchik authored
Summary: Having Indestructible field in SettingsCore makes it leak memory when threads die. Reviewed By: yfeldblum Differential Revision: D10118572 fbshipit-source-id: 68696983128049525018a911b03cb7ea8add53ab
-
Yedidya Feldblum authored
Summary: [Folly] Declare deleted `new` and `delete` operators in pairs in `ScopeGuard`. Reviewed By: Orvid Differential Revision: D10119848 fbshipit-source-id: 3588ed299248efd124d216bfaf5e472795f6a7aa
-
- 29 Sep, 2018 1 commit
-
-
Yedidya Feldblum authored
Summary: [Folly] Closer guarantee of `constexpr` Fingerprint tables computation. Works around a limitation that `template <...> constexpr` functions are only sometimes `constexpr` and may be non-`constexpr` for some instantiations with no warning by enforcing `constexpr` for the instantiations used. Differential Revision: D10116556 fbshipit-source-id: f7014e5b2fce411c27c331874a7fd33841e14df3
-
- 28 Sep, 2018 3 commits
-
-
Dan Melnic authored
Summary: This fixes a linker issue Reviewed By: tuomaspelkonen Differential Revision: D10109866 fbshipit-source-id: bf4193eafc8eb6f75b84241ff6e2ef89ef866642
-
Neel Goyal authored
Summary: SSL_CTX_new can fail if OpenSSL is not initialized. This ensures it is. Reviewed By: bolekk Differential Revision: D10105302 fbshipit-source-id: 4da40d4714747b0e6a359a52fa594fc29bb93c0a
-
Andrii Grynenko authored
Summary: Current thread was previously blocked waiting on the Future to be completed anyway, so there's no reason to not treat it like one of the ObserverManager threads (if it isn't one already) and run the computation inline. Without this change nested makeObserver calls could result in a deadlock if recursion depth was greater than the number of ObserverManager threads. Reviewed By: yfeldblum Differential Revision: D10097363 fbshipit-source-id: eb781ed5aea0ad9415da40fbc7f1c15ed481e92f
-