Commit 68d5fb06 authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

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
parent d51aa234
...@@ -224,6 +224,17 @@ void SingletonHolder<T>::createInstance() { ...@@ -224,6 +224,17 @@ void SingletonHolder<T>::createInstance() {
creating_thread_.store(std::this_thread::get_id(), std::memory_order_release); creating_thread_.store(std::this_thread::get_id(), std::memory_order_release);
auto state = vault_.state_.rlock(); 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) { if (state->state == SingletonVault::SingletonVaultState::Quiescing) {
return; return;
} }
......
...@@ -16,6 +16,10 @@ ...@@ -16,6 +16,10 @@
#include <folly/Singleton.h> #include <folly/Singleton.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
#include <atomic> #include <atomic>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
...@@ -24,8 +28,26 @@ ...@@ -24,8 +28,26 @@
#include <folly/ScopeGuard.h> #include <folly/ScopeGuard.h>
#if !defined(_WIN32) && !defined(__APPLE__)
static void hs_init_weak(int* argc, char** argv[])
__attribute__((__weakref__("hs_init")));
#endif
namespace folly { 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 { namespace detail {
[[noreturn]] void singletonWarnDoubleRegistrationAndAbort( [[noreturn]] void singletonWarnDoubleRegistrationAndAbort(
......
...@@ -358,7 +358,9 @@ class SingletonVault { ...@@ -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. // Destructor is only called by unit tests to check destroyInstances.
~SingletonVault(); ~SingletonVault();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment