From: Andrii Grynenko Date: Tue, 21 Mar 2017 16:45:01 +0000 (-0700) Subject: Don't allow singleton use w/o registrationComplete() X-Git-Tag: v2017.03.27.00~20 X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=68d5fb06281abea91eaa5813e0c919419cc2eb43;p=folly.git Don't allow singleton use w/o registrationComplete() Summary: Submitting mostly to see what breaks. Reviewed By: yfeldblum Differential Revision: D4249032 fbshipit-source-id: d4e3fdfd57750c8dcabdb4c01ab3b528c4818624 --- diff --git a/folly/Singleton-inl.h b/folly/Singleton-inl.h index 2656084e..207a0f7d 100644 --- a/folly/Singleton-inl.h +++ b/folly/Singleton-inl.h @@ -224,6 +224,17 @@ void SingletonHolder::createInstance() { creating_thread_.store(std::this_thread::get_id(), std::memory_order_release); auto state = vault_.state_.rlock(); + if (vault_.type_ != SingletonVault::Type::Relaxed && + !state->registrationComplete) { + auto stack_trace_getter = SingletonVault::stackTraceGetter().load(); + auto stack_trace = stack_trace_getter ? stack_trace_getter() : ""; + if (!stack_trace.empty()) { + stack_trace = "Stack trace:\n" + stack_trace; + } + + LOG(FATAL) << "Singleton " << type().name() << " requested before " + << "registrationComplete() call. " << stack_trace; + } if (state->state == SingletonVault::SingletonVaultState::Quiescing) { return; } diff --git a/folly/Singleton.cpp b/folly/Singleton.cpp index 67e6fd81..4f24328e 100644 --- a/folly/Singleton.cpp +++ b/folly/Singleton.cpp @@ -16,6 +16,10 @@ #include +#ifndef _WIN32 +#include +#endif + #include #include #include @@ -24,8 +28,26 @@ #include +#if !defined(_WIN32) && !defined(__APPLE__) +static void hs_init_weak(int* argc, char** argv[]) + __attribute__((__weakref__("hs_init"))); +#endif + namespace folly { +SingletonVault::Type SingletonVault::defaultVaultType() { +#if !defined(_WIN32) && !defined(__APPLE__) + bool isPython = dlsym(RTLD_DEFAULT, "Py_Main"); + bool isHaskel = &::hs_init_weak || dlsym(RTLD_DEFAULT, "hs_init"); + bool isJVM = dlsym(RTLD_DEFAULT, "JNI_GetCreatedJavaVMs"); + bool isD = dlsym(RTLD_DEFAULT, "_d_run_main"); + + return isPython || isHaskel || isJVM || isD ? Type::Relaxed : Type::Strict; +#else + return Type::Relaxed; +#endif +} + namespace detail { [[noreturn]] void singletonWarnDoubleRegistrationAndAbort( diff --git a/folly/Singleton.h b/folly/Singleton.h index 2c699e47..e8344cef 100644 --- a/folly/Singleton.h +++ b/folly/Singleton.h @@ -358,7 +358,9 @@ class SingletonVault { } }; - explicit SingletonVault(Type type = Type::Strict) : type_(type) {} + static Type defaultVaultType(); + + explicit SingletonVault(Type type = defaultVaultType()) : type_(type) {} // Destructor is only called by unit tests to check destroyInstances. ~SingletonVault();