Commit 7d0d018f authored by Andrii Grynenko's avatar Andrii Grynenko Committed by Facebook Github Bot

Don't allow singleton use w/o registrationComplete()

Summary: This is same as D4249032, but for now this is only enabled in dbg and dev builds. I'm planning to bump this to FATAL later, once we fix know problematic main()s.

Reviewed By: lbrandy, yfeldblum

Differential Revision: D4821763

fbshipit-source-id: 5f7930f8cbcb10275d23a89848f1ec8ee34a8020
parent 0fdbb3df
......@@ -230,6 +230,17 @@ void SingletonHolder<T>::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(DFATAL) << "Singleton " << type().name() << " requested before "
<< "registrationComplete() call. " << stack_trace;
}
if (state->state == SingletonVault::SingletonVaultState::Quiescing) {
return;
}
......
......@@ -16,6 +16,10 @@
#include <folly/Singleton.h>
#ifndef _WIN32
#include <dlfcn.h>
#endif
#include <atomic>
#include <cstdio>
#include <cstdlib>
......@@ -24,8 +28,26 @@
#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 {
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(
......
......@@ -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();
......
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