From: Andrii Grynenko <andrii@fb.com>
Date: Tue, 29 Nov 2016 23:34:43 +0000 (-0800)
Subject: Disallow folly::Singletons before main()
X-Git-Tag: v2016.12.05.00~13
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=ee43735cc06a4243e6676b332035927715643be7;p=folly.git

Disallow folly::Singletons before main()

Summary:
Make folly::Singleton fail if singleton is requested before registrationComplete. By doing this we disallow any folly::Singleton to be created before main().

Strict mode is still disabled for Python and Hs.

Reviewed By: yfeldblum

Differential Revision: D4121322

fbshipit-source-id: b66c23e24f6a7324cd12ddb77cad960e0950a1aa
---

diff --git a/folly/Singleton-inl.h b/folly/Singleton-inl.h
index 4a6c071b..a0c8cd93 100644
--- a/folly/Singleton-inl.h
+++ b/folly/Singleton-inl.h
@@ -225,9 +225,6 @@ void SingletonHolder<T>::createInstance() {
 
   auto state = vault_.state_.rlock();
   if (state->state == SingletonVault::SingletonVaultState::Quiescing) {
-    if (vault_.type_ != SingletonVault::Type::Relaxed) {
-      LOG(FATAL) << "Requesting singleton after vault was destroyed.";
-    }
     return;
   }
 
diff --git a/folly/Singleton.cpp b/folly/Singleton.cpp
index 5e89442c..6a240181 100644
--- a/folly/Singleton.cpp
+++ b/folly/Singleton.cpp
@@ -103,12 +103,17 @@ void SingletonVault::registrationComplete() {
   auto state = state_.wlock();
   stateCheck(SingletonVaultState::Running, *state);
 
+  if (state->registrationComplete) {
+    return;
+  }
+
   auto singletons = singletons_.rlock();
   if (type_ == Type::Strict) {
     for (const auto& p : *singletons) {
       if (p.second->hasLiveInstance()) {
         throw std::runtime_error(
-            "Singleton created before registration was complete.");
+            "Singleton " + p.first.name() +
+            " created before registration was complete.");
       }
     }
   }
diff --git a/folly/Singleton.h b/folly/Singleton.h
index c377f3ad..9c575ed7 100644
--- a/folly/Singleton.h
+++ b/folly/Singleton.h
@@ -348,7 +348,7 @@ class SingletonVault {
     }
   };
 
-  explicit SingletonVault(Type type = Type::Relaxed) : type_(type) {}
+  explicit SingletonVault(Type type = Type::Strict) : type_(type) {}
 
   // Destructor is only called by unit tests to check destroyInstances.
   ~SingletonVault();
@@ -509,7 +509,7 @@ class SingletonVault {
 
   folly::Synchronized<State> state_;
 
-  Type type_{Type::Relaxed};
+  Type type_;
 };
 
 // This is the wrapper class that most users actually interact with.
diff --git a/folly/test/SingletonTest.cpp b/folly/test/SingletonTest.cpp
index aa068911..40e12b98 100644
--- a/folly/test/SingletonTest.cpp
+++ b/folly/test/SingletonTest.cpp
@@ -393,8 +393,8 @@ template <typename T, typename Tag = detail::DefaultTag>
 using SingletonCreationError = Singleton<T, Tag, CreationErrorTag>;
 
 TEST(Singleton, SingletonCreationError) {
-  SingletonVault::singleton<CreationErrorTag>();
   SingletonCreationError<ErrorConstructor> error_once_singleton;
+  SingletonVault::singleton<CreationErrorTag>()->registrationComplete();
 
   // first time should error out
   EXPECT_THROW(error_once_singleton.try_get(), std::runtime_error);
@@ -411,6 +411,7 @@ using SingletonConcurrencyStress = Singleton <T, Tag, ConcurrencyStressTag>;
 TEST(Singleton, SingletonConcurrencyStress) {
   auto& vault = *SingletonVault::singleton<ConcurrencyStressTag>();
   SingletonConcurrencyStress<Slowpoke> slowpoke_singleton;
+  vault.registrationComplete();
 
   std::vector<std::thread> ts;
   for (size_t i = 0; i < 100; ++i) {