Commit d1c5974b authored by Cameron Pickett's avatar Cameron Pickett Committed by Facebook Github Bot

Handle nullptr from getTimekeeperSingleton

Summary:
According to folly::Singleton::try_get(), https://fburl.com/23wqby9i, the caller is responsible for handling a nullptr return. In this case, we handle it poorly, via a crash both in production and debug code.

This diff opts for handling the nullptr more gracefully, via a future loaded with an exception.

Reviewed By: yfeldblum

Differential Revision: D6006864

fbshipit-source-id: e8fde57ed161b33fa1f157ce663ed85e69640c25
parent fbc4c238
...@@ -41,8 +41,13 @@ Future<Unit> sleep(Duration dur, Timekeeper* tk) { ...@@ -41,8 +41,13 @@ Future<Unit> sleep(Duration dur, Timekeeper* tk) {
std::shared_ptr<Timekeeper> tks; std::shared_ptr<Timekeeper> tks;
if (LIKELY(!tk)) { if (LIKELY(!tk)) {
tks = folly::detail::getTimekeeperSingleton(); tks = folly::detail::getTimekeeperSingleton();
tk = DCHECK_NOTNULL(tks.get()); tk = tks.get();
} }
if (UNLIKELY(!tk)) {
return makeFuture<Unit>(NoTimekeeper());
}
return tk->after(dur); return tk->after(dur);
} }
......
...@@ -83,9 +83,15 @@ class FOLLY_EXPORT PredicateDoesNotObtain : public FutureException { ...@@ -83,9 +83,15 @@ class FOLLY_EXPORT PredicateDoesNotObtain : public FutureException {
[[noreturn]] void throwPredicateDoesNotObtain(); [[noreturn]] void throwPredicateDoesNotObtain();
struct FOLLY_EXPORT NoFutureInSplitter : FutureException { class FOLLY_EXPORT NoFutureInSplitter : FutureException {
public:
NoFutureInSplitter() : FutureException("No Future in this FutureSplitter") {} NoFutureInSplitter() : FutureException("No Future in this FutureSplitter") {}
}; };
[[noreturn]] void throwNoFutureInSplitter(); [[noreturn]] void throwNoFutureInSplitter();
class FOLLY_EXPORT NoTimekeeper : public FutureException {
public:
NoTimekeeper() : FutureException("No timekeeper available") {}
};
} }
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
#include <folly/futures/Timekeeper.h> #include <folly/futures/Timekeeper.h>
#include <folly/Singleton.h>
#include <folly/futures/ThreadWheelTimekeeper.h>
#include <folly/portability/GTest.h> #include <folly/portability/GTest.h>
using namespace folly; using namespace folly;
...@@ -78,6 +80,14 @@ TEST(Timekeeper, futureSleep) { ...@@ -78,6 +80,14 @@ TEST(Timekeeper, futureSleep) {
EXPECT_GE(now() - t1, one_ms); EXPECT_GE(now() - t1, one_ms);
} }
TEST(Timekeeper, futureSleepHandlesNullTimekeeperSingleton) {
Singleton<ThreadWheelTimekeeper>::make_mock([] { return nullptr; });
SCOPE_EXIT {
Singleton<ThreadWheelTimekeeper>::make_mock();
};
EXPECT_THROW(futures::sleep(one_ms).get(), NoTimekeeper);
}
TEST(Timekeeper, futureDelayed) { TEST(Timekeeper, futureDelayed) {
auto t1 = now(); auto t1 = now();
auto dur = makeFuture() auto dur = makeFuture()
......
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