2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/Singleton.h>
29 #include <folly/Demangle.h>
30 #include <folly/Format.h>
31 #include <folly/ScopeGuard.h>
33 #if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__)
34 #define FOLLY_SINGLETON_HAVE_DLSYM 1
39 #if FOLLY_SINGLETON_HAVE_DLSYM
41 static void singleton_hs_init_weak(int* argc, char** argv[])
42 __attribute__((__weakref__("hs_init")));
46 SingletonVault::Type SingletonVault::defaultVaultType() {
47 #if FOLLY_SINGLETON_HAVE_DLSYM
48 bool isPython = dlsym(RTLD_DEFAULT, "Py_Main");
50 detail::singleton_hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init");
51 bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs");
52 bool isD = dlsym(RTLD_DEFAULT, "_d_run_main");
54 return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict;
62 std::string TypeDescriptor::name() const {
63 auto ret = demangle(ti_.name());
64 if (tag_ti_ != std::type_index(typeid(DefaultTag))) {
66 ret += demangle(tag_ti_.name());
68 return ret.toStdString();
71 [[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
72 const TypeDescriptor& type) {
73 // Ensure the availability of std::cerr
74 std::ios_base::Init ioInit;
75 std::cerr << "Double registration of singletons of the same "
76 "underlying type; check for multiple definitions "
77 "of type folly::Singleton<"
78 << type.name() << ">\n";
82 [[noreturn]] void singletonWarnLeakyDoubleRegistrationAndAbort(
83 const TypeDescriptor& type) {
84 // Ensure the availability of std::cerr
85 std::ios_base::Init ioInit;
86 std::cerr << "Double registration of singletons of the same "
87 "underlying type; check for multiple definitions "
88 "of type folly::LeakySingleton<"
89 << type.name() << ">\n";
93 [[noreturn]] void singletonWarnLeakyInstantiatingNotRegisteredAndAbort(
94 const TypeDescriptor& type) {
95 auto ptr = SingletonVault::stackTraceGetter().load();
96 LOG(FATAL) << "Creating instance for unregistered singleton: "
97 << type.name() << "\n"
99 << "\n" << (ptr ? (*ptr)() : "(not available)");
102 [[noreturn]] void singletonWarnRegisterMockEarlyAndAbort(
103 const TypeDescriptor& type) {
104 LOG(FATAL) << "Registering mock before singleton was registered: "
108 void singletonWarnDestroyInstanceLeak(
109 const TypeDescriptor& type,
111 LOG(ERROR) << "Singleton of type " << type.name() << " has a "
112 << "living reference at destroyInstances time; beware! Raw "
113 << "pointer is " << ptr << ". It is very likely "
114 << "that some other singleton is holding a shared_ptr to it. "
115 << "This singleton will be leaked (even if a shared_ptr to it "
116 << "is eventually released)."
117 << "Make sure dependencies between these singletons are "
118 << "properly defined.";
121 [[noreturn]] void singletonWarnCreateCircularDependencyAndAbort(
122 const TypeDescriptor& type) {
123 LOG(FATAL) << "circular singleton dependency: " << type.name();
126 [[noreturn]] void singletonWarnCreateUnregisteredAndAbort(
127 const TypeDescriptor& type) {
128 auto ptr = SingletonVault::stackTraceGetter().load();
129 LOG(FATAL) << "Creating instance for unregistered singleton: "
130 << type.name() << "\n"
133 << (ptr ? (*ptr)() : "(not available)");
136 [[noreturn]] void singletonWarnCreateBeforeRegistrationCompleteAndAbort(
137 const TypeDescriptor& type) {
138 auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
139 auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
140 if (!stack_trace.empty()) {
141 stack_trace = "Stack trace:\n" + stack_trace;
144 LOG(FATAL) << "Singleton " << type.name() << " requested before "
145 << "registrationComplete() call.\n"
146 << "This usually means that either main() never called "
147 << "folly::init, or singleton was requested before main() "
148 << "(which is not allowed).\n"
152 void singletonPrintDestructionStackTrace(const TypeDescriptor& type) {
153 std::string output = "Singleton " + type.name() + " was released.\n";
155 auto stack_trace_getter = SingletonVault::stackTraceGetter().load();
156 auto stack_trace = stack_trace_getter ? stack_trace_getter() : "";
157 if (stack_trace.empty()) {
158 output += "Failed to get release stack trace.";
160 output += "Release stack trace:\n";
161 output += stack_trace;
164 LOG(ERROR) << output;
167 [[noreturn]] void singletonThrowNullCreator(const std::type_info& type) {
168 auto const msg = sformat(
169 "nullptr_t should be passed if you want {} to be default constructed",
171 throw std::logic_error(msg);
174 [[noreturn]] void singletonThrowGetInvokedAfterDestruction(
175 const TypeDescriptor& type) {
176 throw std::runtime_error(
177 "Raw pointer to a singleton requested after its destruction."
178 " Singleton type is: " +
182 [[noreturn]] void SingletonVaultState::throwUnexpectedState(const char* msg) {
183 throw std::logic_error(msg);
186 } // namespace detail
192 if (!leakedSingletons_.empty()) {
193 std::string leakedTypes;
194 for (const auto& singleton : leakedSingletons_) {
195 leakedTypes += "\t" + singleton.name() + "\n";
197 LOG(DFATAL) << "Singletons of the following types had living references "
198 << "after destroyInstances was finished:\n" << leakedTypes
199 << "beware! It is very likely that those singleton instances "
204 std::vector<detail::TypeDescriptor> leakedSingletons_;
207 #if defined(__APPLE__) || defined(_MSC_VER)
208 // OS X doesn't support constructor priorities.
209 FatalHelper fatalHelper;
211 FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
216 SingletonVault::~SingletonVault() { destroyInstances(); }
218 void SingletonVault::registerSingleton(detail::SingletonHolderBase* entry) {
219 auto state = state_.rlock();
220 state->check(detail::SingletonVaultState::Type::Running);
222 if (UNLIKELY(state->registrationComplete)) {
223 LOG(ERROR) << "Registering singleton after registrationComplete().";
226 auto singletons = singletons_.wlock();
228 singletons->emplace(entry->type(), entry).second, std::logic_error);
231 void SingletonVault::addEagerInitSingleton(detail::SingletonHolderBase* entry) {
232 auto state = state_.rlock();
233 state->check(detail::SingletonVaultState::Type::Running);
235 if (UNLIKELY(state->registrationComplete)) {
236 LOG(ERROR) << "Registering for eager-load after registrationComplete().";
239 CHECK_THROW(singletons_.rlock()->count(entry->type()), std::logic_error);
241 auto eagerInitSingletons = eagerInitSingletons_.wlock();
242 eagerInitSingletons->insert(entry);
245 void SingletonVault::registrationComplete() {
246 std::atexit([](){ SingletonVault::singleton()->destroyInstances(); });
248 auto state = state_.wlock();
249 state->check(detail::SingletonVaultState::Type::Running);
251 if (state->registrationComplete) {
255 auto singletons = singletons_.rlock();
256 if (type_ == Type::Strict) {
257 for (const auto& p : *singletons) {
258 if (p.second->hasLiveInstance()) {
259 throw std::runtime_error(
260 "Singleton " + p.first.name() +
261 " created before registration was complete.");
266 state->registrationComplete = true;
269 void SingletonVault::doEagerInit() {
271 auto state = state_.rlock();
272 state->check(detail::SingletonVaultState::Type::Running);
273 if (UNLIKELY(!state->registrationComplete)) {
274 throw std::logic_error("registrationComplete() not yet called");
278 auto eagerInitSingletons = eagerInitSingletons_.rlock();
279 for (auto* single : *eagerInitSingletons) {
280 single->createInstance();
284 void SingletonVault::doEagerInitVia(Executor& exe, folly::Baton<>* done) {
286 auto state = state_.rlock();
287 state->check(detail::SingletonVaultState::Type::Running);
288 if (UNLIKELY(!state->registrationComplete)) {
289 throw std::logic_error("registrationComplete() not yet called");
293 auto eagerInitSingletons = eagerInitSingletons_.rlock();
295 std::make_shared<std::atomic<size_t>>(eagerInitSingletons->size());
296 for (auto* single : *eagerInitSingletons) {
297 // countdown is retained by shared_ptr, and will be alive until last lambda
298 // is done. notifyBaton is provided by the caller, and expected to remain
299 // present (if it's non-nullptr). singletonSet can go out of scope but
300 // its values, which are SingletonHolderBase pointers, are alive as long as
301 // SingletonVault is not being destroyed.
303 // decrement counter and notify if requested, whether initialization
304 // was successful, was skipped (already initialized), or exception thrown.
306 if (--(*countdown) == 0) {
307 if (done != nullptr) {
312 // if initialization is in progress in another thread, don't try to init
313 // here. Otherwise the current thread will block on 'createInstance'.
314 if (!single->creationStarted()) {
315 single->createInstance();
321 void SingletonVault::destroyInstances() {
322 auto stateW = state_.wlock();
323 if (stateW->state == detail::SingletonVaultState::Type::Quiescing) {
326 stateW->state = detail::SingletonVaultState::Type::Quiescing;
328 auto stateR = stateW.moveFromWriteToRead();
330 auto singletons = singletons_.rlock();
331 auto creationOrder = creationOrder_.rlock();
333 CHECK_GE(singletons->size(), creationOrder->size());
335 // Release all ReadMostlyMainPtrs at once
337 ReadMostlyMainPtrDeleter<> deleter;
338 for (auto& singleton_type : *creationOrder) {
339 singletons->at(singleton_type)->preDestroyInstance(deleter);
343 for (auto type_iter = creationOrder->rbegin();
344 type_iter != creationOrder->rend();
346 singletons->at(*type_iter)->destroyInstance();
349 for (auto& singleton_type : *creationOrder) {
350 auto singleton = singletons->at(singleton_type);
351 if (!singleton->hasLiveInstance()) {
355 fatalHelper.leakedSingletons_.push_back(singleton->type());
360 auto creationOrder = creationOrder_.wlock();
361 creationOrder->clear();
365 void SingletonVault::reenableInstances() {
366 auto state = state_.wlock();
368 state->check(detail::SingletonVaultState::Type::Quiescing);
370 state->state = detail::SingletonVaultState::Type::Running;
373 void SingletonVault::scheduleDestroyInstances() {
374 // Add a dependency on folly::ThreadLocal to make sure all its static
375 // singletons are initalized first.
376 threadlocal_detail::StaticMeta<void, void>::instance();
378 class SingletonVaultDestructor {
380 ~SingletonVaultDestructor() {
381 SingletonVault::singleton()->destroyInstances();
385 // Here we intialize a singleton, which calls destroyInstances in its
386 // destructor. Because of singleton destruction order - it will be destroyed
387 // before all the singletons, which were initialized before it and after all
388 // the singletons initialized after it.
389 static SingletonVaultDestructor singletonVaultDestructor;