Singleton.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*
  2. * Copyright 2014-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/Singleton.h>
  17. #include <folly/portability/Config.h>
  18. #ifndef _WIN32
  19. #include <dlfcn.h>
  20. #endif
  21. #include <atomic>
  22. #include <cstdio>
  23. #include <cstdlib>
  24. #include <iostream>
  25. #include <string>
  26. #include <folly/Demangle.h>
  27. #include <folly/Format.h>
  28. #include <folly/ScopeGuard.h>
  29. #if FOLLY_USE_SYMBOLIZER
  30. #include <folly/experimental/symbolizer/Symbolizer.h> // @manual
  31. #endif
  32. #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__)
  33. #define FOLLY_SINGLETON_HAVE_DLSYM 1
  34. #endif
  35. namespace folly {
  36. #if FOLLY_SINGLETON_HAVE_DLSYM
  37. namespace detail {
  38. static void singleton_hs_init_weak(int* argc, char** argv[])
  39. __attribute__((__weakref__("hs_init")));
  40. } // namespace detail
  41. #endif
  42. SingletonVault::Type SingletonVault::defaultVaultType() {
  43. #if FOLLY_SINGLETON_HAVE_DLSYM
  44. bool isPython = dlsym(RTLD_DEFAULT, "Py_Main");
  45. bool isHaskel =
  46. detail::singleton_hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init");
  47. bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs");
  48. bool isD = dlsym(RTLD_DEFAULT, "_d_run_main");
  49. return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict;
  50. #else
  51. return Type::Relaxed;
  52. #endif
  53. }
  54. namespace detail {
  55. std::string TypeDescriptor::name() const {
  56. auto ret = demangle(ti_.name());
  57. if (tag_ti_ != std::type_index(typeid(DefaultTag))) {
  58. ret += "/";
  59. ret += demangle(tag_ti_.name());
  60. }
  61. return ret.toStdString();
  62. }
  63. // clang-format off
  64. [[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
  65. const TypeDescriptor& type) {
  66. // Ensure the availability of std::cerr
  67. std::ios_base::Init ioInit;
  68. std::cerr << "Double registration of singletons of the same "
  69. "underlying type; check for multiple definitions "
  70. "of type folly::Singleton<"
  71. << type.name() << ">\n";
  72. std::abort();
  73. }
  74. [[noreturn]] void singletonWarnLeakyDoubleRegistrationAndAbort(
  75. const TypeDescriptor& type) {
  76. // Ensure the availability of std::cerr
  77. std::ios_base::Init ioInit;
  78. std::cerr << "Double registration of singletons of the same "
  79. "underlying type; check for multiple definitions "
  80. "of type folly::LeakySingleton<"
  81. << type.name() << ">\n";
  82. std::abort();
  83. }
  84. [[noreturn]] void singletonWarnLeakyInstantiatingNotRegisteredAndAbort(
  85. const TypeDescriptor& type) {
  86. auto ptr = SingletonVault::stackTraceGetter().load();
  87. LOG(FATAL) << "Creating instance for unregistered singleton: " << type.name()
  88. << "\n"
  89. << "Stacktrace:"
  90. << "\n"
  91. << (ptr ? (*ptr)() : "(not available)");
  92. }
  93. [[noreturn]] void singletonWarnRegisterMockEarlyAndAbort(
  94. const TypeDescriptor& type) {
  95. LOG(FATAL) << "Registering mock before singleton was registered: "
  96. << type.name();
  97. }
  98. void singletonWarnDestroyInstanceLeak(
  99. const TypeDescriptor& type,
  100. const void* ptr) {
  101. LOG(ERROR) << "Singleton of type " << type.name() << " has a "
  102. << "living reference at destroyInstances time; beware! Raw "
  103. << "pointer is " << ptr << ". It is very likely "
  104. << "that some other singleton is holding a shared_ptr to it. "
  105. << "This singleton will be leaked (even if a shared_ptr to it "
  106. << "is eventually released)."
  107. << "Make sure dependencies between these singletons are "
  108. << "properly defined.";
  109. }
  110. [[noreturn]] void singletonWarnCreateCircularDependencyAndAbort(
  111. const TypeDescriptor& type) {
  112. LOG(FATAL) << "circular singleton dependency: " << type.name();
  113. }
  114. [[noreturn]] void singletonWarnCreateUnregisteredAndAbort(
  115. const TypeDescriptor& type) {
  116. auto ptr = SingletonVault::stackTraceGetter().load();
  117. LOG(FATAL) << "Creating instance for unregistered singleton: " << type.name()
  118. << "\n"
  119. << "Stacktrace:"
  120. << "\n"
  121. << (ptr ? (*ptr)() : "(not available)");
  122. }
  123. [[noreturn]] void singletonWarnCreateBeforeRegistrationCompleteAndAbort(
  124. const TypeDescriptor& type) {
  125. auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
  126. auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
  127. if (!stack_trace.empty()) {
  128. stack_trace = "Stack trace:\n" + stack_trace;
  129. }
  130. LOG(FATAL) << "Singleton " << type.name() << " requested before "
  131. << "registrationComplete() call.\n"
  132. << "This usually means that either main() never called "
  133. << "folly::init, or singleton was requested before main() "
  134. << "(which is not allowed).\n"
  135. << stack_trace;
  136. }
  137. void singletonPrintDestructionStackTrace(const TypeDescriptor& type) {
  138. std::string output = "Singleton " + type.name() + " was released.\n";
  139. auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
  140. auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
  141. if (stack_trace.empty()) {
  142. output += "Failed to get release stack trace.";
  143. } else {
  144. output += "Release stack trace:\n";
  145. output += stack_trace;
  146. }
  147. LOG(ERROR) << output;
  148. }
  149. [[noreturn]] void singletonThrowNullCreator(const std::type_info& type) {
  150. auto const msg = sformat(
  151. "nullptr_t should be passed if you want {} to be default constructed",
  152. demangle(type));
  153. throw std::logic_error(msg);
  154. }
  155. [[noreturn]] void singletonThrowGetInvokedAfterDestruction(
  156. const TypeDescriptor& type) {
  157. throw std::runtime_error(
  158. "Raw pointer to a singleton requested after its destruction."
  159. " Singleton type is: " +
  160. type.name());
  161. }
  162. // clang-format on
  163. } // namespace detail
  164. namespace {
  165. struct FatalHelper {
  166. ~FatalHelper() {
  167. if (!leakedSingletons_.empty()) {
  168. std::string leakedTypes;
  169. for (const auto& singleton : leakedSingletons_) {
  170. leakedTypes += "\t" + singleton.name() + "\n";
  171. }
  172. LOG(DFATAL) << "Singletons of the following types had living references "
  173. << "after destroyInstances was finished:\n"
  174. << leakedTypes
  175. << "beware! It is very likely that those singleton instances "
  176. << "are leaked.";
  177. }
  178. }
  179. std::vector<detail::TypeDescriptor> leakedSingletons_;
  180. };
  181. #if defined(__APPLE__) || defined(_MSC_VER)
  182. // OS X doesn't support constructor priorities.
  183. FatalHelper fatalHelper;
  184. #else
  185. FatalHelper __attribute__((__init_priority__(101))) fatalHelper;
  186. #endif
  187. } // namespace
  188. SingletonVault::~SingletonVault() {
  189. destroyInstances();
  190. }
  191. void SingletonVault::registerSingleton(detail::SingletonHolderBase* entry) {
  192. auto state = state_.rlock();
  193. state->check(detail::SingletonVaultState::Type::Running);
  194. if (UNLIKELY(state->registrationComplete)) {
  195. LOG(ERROR) << "Registering singleton after registrationComplete().";
  196. }
  197. auto singletons = singletons_.wlock();
  198. CHECK_THROW(
  199. singletons->emplace(entry->type(), entry).second, std::logic_error);
  200. }
  201. void SingletonVault::addEagerInitSingleton(detail::SingletonHolderBase* entry) {
  202. auto state = state_.rlock();
  203. state->check(detail::SingletonVaultState::Type::Running);
  204. if (UNLIKELY(state->registrationComplete)) {
  205. LOG(ERROR) << "Registering for eager-load after registrationComplete().";
  206. }
  207. CHECK_THROW(singletons_.rlock()->count(entry->type()), std::logic_error);
  208. auto eagerInitSingletons = eagerInitSingletons_.wlock();
  209. eagerInitSingletons->insert(entry);
  210. }
  211. void SingletonVault::registrationComplete() {
  212. std::atexit([]() { SingletonVault::singleton()->destroyInstances(); });
  213. auto state = state_.wlock();
  214. state->check(detail::SingletonVaultState::Type::Running);
  215. if (state->registrationComplete) {
  216. return;
  217. }
  218. auto singletons = singletons_.rlock();
  219. if (type_ == Type::Strict) {
  220. for (const auto& p : *singletons) {
  221. if (p.second->hasLiveInstance()) {
  222. throw std::runtime_error(
  223. "Singleton " + p.first.name() +
  224. " created before registration was complete.");
  225. }
  226. }
  227. }
  228. state->registrationComplete = true;
  229. }
  230. void SingletonVault::doEagerInit() {
  231. {
  232. auto state = state_.rlock();
  233. state->check(detail::SingletonVaultState::Type::Running);
  234. if (UNLIKELY(!state->registrationComplete)) {
  235. throw std::logic_error("registrationComplete() not yet called");
  236. }
  237. }
  238. auto eagerInitSingletons = eagerInitSingletons_.rlock();
  239. for (auto* single : *eagerInitSingletons) {
  240. single->createInstance();
  241. }
  242. }
  243. void SingletonVault::doEagerInitVia(Executor& exe, folly::Baton<>* done) {
  244. {
  245. auto state = state_.rlock();
  246. state->check(detail::SingletonVaultState::Type::Running);
  247. if (UNLIKELY(!state->registrationComplete)) {
  248. throw std::logic_error("registrationComplete() not yet called");
  249. }
  250. }
  251. auto eagerInitSingletons = eagerInitSingletons_.rlock();
  252. auto countdown =
  253. std::make_shared<std::atomic<size_t>>(eagerInitSingletons->size());
  254. for (auto* single : *eagerInitSingletons) {
  255. // countdown is retained by shared_ptr, and will be alive until last lambda
  256. // is done. notifyBaton is provided by the caller, and expected to remain
  257. // present (if it's non-nullptr). singletonSet can go out of scope but
  258. // its values, which are SingletonHolderBase pointers, are alive as long as
  259. // SingletonVault is not being destroyed.
  260. exe.add([=] {
  261. // decrement counter and notify if requested, whether initialization
  262. // was successful, was skipped (already initialized), or exception thrown.
  263. SCOPE_EXIT {
  264. if (--(*countdown) == 0) {
  265. if (done != nullptr) {
  266. done->post();
  267. }
  268. }
  269. };
  270. // if initialization is in progress in another thread, don't try to init
  271. // here. Otherwise the current thread will block on 'createInstance'.
  272. if (!single->creationStarted()) {
  273. single->createInstance();
  274. }
  275. });
  276. }
  277. }
  278. void SingletonVault::destroyInstances() {
  279. auto stateW = state_.wlock();
  280. if (stateW->state == detail::SingletonVaultState::Type::Quiescing) {
  281. return;
  282. }
  283. stateW->state = detail::SingletonVaultState::Type::Quiescing;
  284. auto stateR = stateW.moveFromWriteToRead();
  285. {
  286. auto singletons = singletons_.rlock();
  287. auto creationOrder = creationOrder_.rlock();
  288. CHECK_GE(singletons->size(), creationOrder->size());
  289. // Release all ReadMostlyMainPtrs at once
  290. {
  291. ReadMostlyMainPtrDeleter<> deleter;
  292. for (auto& singleton_type : *creationOrder) {
  293. singletons->at(singleton_type)->preDestroyInstance(deleter);
  294. }
  295. }
  296. for (auto type_iter = creationOrder->rbegin();
  297. type_iter != creationOrder->rend();
  298. ++type_iter) {
  299. singletons->at(*type_iter)->destroyInstance();
  300. }
  301. for (auto& singleton_type : *creationOrder) {
  302. auto instance = singletons->at(singleton_type);
  303. if (!instance->hasLiveInstance()) {
  304. continue;
  305. }
  306. fatalHelper.leakedSingletons_.push_back(instance->type());
  307. }
  308. }
  309. {
  310. auto creationOrder = creationOrder_.wlock();
  311. creationOrder->clear();
  312. }
  313. }
  314. void SingletonVault::reenableInstances() {
  315. auto state = state_.wlock();
  316. state->check(detail::SingletonVaultState::Type::Quiescing);
  317. state->state = detail::SingletonVaultState::Type::Running;
  318. }
  319. void SingletonVault::scheduleDestroyInstances() {
  320. // Add a dependency on folly::ThreadLocal to make sure all its static
  321. // singletons are initalized first.
  322. threadlocal_detail::StaticMeta<void, void>::instance();
  323. std::atexit([] { SingletonVault::singleton()->destroyInstances(); });
  324. }
  325. // If we're using folly's Symbolizer, create a static initializer to setup
  326. // Singltone's to use it to print stack traces. It's important that we keep
  327. // this in the same compilation unit as the `SingletonVault` so that it's
  328. // setup/used iff singleton's are used.
  329. #if FOLLY_USE_SYMBOLIZER
  330. namespace {
  331. std::string stackTraceGetter() {
  332. // Get and symbolize stack trace
  333. constexpr size_t kMaxStackTraceDepth = 100;
  334. symbolizer::FrameArray<kMaxStackTraceDepth> addresses;
  335. if (!getStackTraceSafe(addresses)) {
  336. return "";
  337. } else {
  338. constexpr size_t kDefaultCapacity = 500;
  339. symbolizer::ElfCache elfCache(kDefaultCapacity);
  340. symbolizer::Symbolizer symbolizer(&elfCache);
  341. symbolizer.symbolize(addresses);
  342. symbolizer::StringSymbolizePrinter printer;
  343. printer.println(addresses);
  344. return printer.str();
  345. }
  346. }
  347. struct SetStackTraceGetter {
  348. SetStackTraceGetter() {
  349. SingletonVault::stackTraceGetter().store(stackTraceGetter);
  350. }
  351. };
  352. #ifdef __APPLE__
  353. // OS X doesn't support constructor priorities.
  354. SetStackTraceGetter setStackTraceGetter;
  355. #else
  356. SetStackTraceGetter __attribute__((__init_priority__(101))) setStackTraceGetter;
  357. #endif
  358. } // namespace
  359. #endif
  360. } // namespace folly