Make folly::Singleton DFATAL as late as possible
authorAndrii Grynenko <andrii@fb.com>
Fri, 20 Mar 2015 19:17:17 +0000 (12:17 -0700)
committerNoam Lerner <noamler@fb.com>
Wed, 25 Mar 2015 22:35:24 +0000 (15:35 -0700)
Summary: We want to print all destructor stack-traces if Singleton destruction happens eventually (even after destroyInstances() was done).

Test Plan:
unit test

Reviewed By: chip@fb.com

Subscribers: folly-diffs@, yfeldblum

FB internal diff: D1929881

Signature: t1:1929881:1426878091:5993d544c0f84bdbf8bcdd420ef01fb7bf88ac3f

folly/experimental/Singleton.cpp

index 7421f4bc979684c4b9a22e52734c7c654e5c99a5..1c39326ecdf9fef2622195aa36b39b3dc1fd4cae 100644 (file)
@@ -26,6 +26,29 @@ constexpr std::chrono::seconds SingletonHolderBase::kDestroyWaitTime;
 
 }
 
+namespace {
+
+struct FatalHelper {
+  ~FatalHelper() {
+    if (!leakedSingletons_.empty()) {
+      std::string leakedTypes;
+      for (const auto& singleton : leakedSingletons_) {
+        leakedTypes += "\t" + singleton.name() + "\n";
+      }
+      LOG(DFATAL) << "Singletons of the following types had living references "
+                  << "after destroyInstances was finished:\n" << leakedTypes
+                  << "beware! It is very likely that those singleton instances "
+                  << "are leaked.";
+    }
+  }
+
+  std::vector<detail::TypeDescriptor> leakedSingletons_;
+};
+
+FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
+
+}
+
 SingletonVault::~SingletonVault() { destroyInstances(); }
 
 void SingletonVault::destroyInstances() {
@@ -55,10 +78,7 @@ void SingletonVault::destroyInstances() {
         continue;
       }
 
-      LOG(DFATAL) << "Singleton of type " << singleton->type().name() << " has "
-                  << "a living reference after destroyInstances was finished;"
-                  << "beware! It is very likely that this singleton instance "
-                  << "will be leaked.";
+      fatalHelper.leakedSingletons_.push_back(singleton->type());
     }
   }