Move threadlocal_detail::Atfork to its own file
[folly.git] / folly / Singleton.cpp
index fe8d7db7a17b38b4e94e43b557fdd972918a04ab..7114d53de9df1ca16c630913636a4dc6436e1ddf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <folly/Singleton.h>
 
+#ifndef _WIN32
+#include <dlfcn.h>
+#endif
+
 #include <atomic>
 #include <cstdio>
 #include <cstdlib>
-#include <sstream>
+#include <iostream>
 #include <string>
 
-#include <folly/FileUtil.h>
 #include <folly/ScopeGuard.h>
 
+#if !defined(_WIN32) && !defined(__APPLE__) && !defined(__ANDROID__)
+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__) && !defined(__ANDROID__)
+  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(
     const TypeDescriptor& type) {
-  // Not using LOG(FATAL) or std::cerr because they may not be initialized yet.
-  std::ostringstream o;
-  o << "Double registration of singletons of the same "
-    << "underlying type; check for multiple definitions "
-    << "of type folly::Singleton<" << type.name() << ">" << std::endl;
-  auto s = o.str();
-  writeFull(STDERR_FILENO, s.data(), s.size());
+  // Ensure the availability of std::cerr
+  std::ios_base::Init ioInit;
+  std::cerr << "Double registration of singletons of the same "
+               "underlying type; check for multiple definitions "
+               "of type folly::Singleton<"
+            << type.name() << ">\n";
   std::abort();
 }
-}
+} // namespace detail
 
 namespace {
 
@@ -68,7 +88,7 @@ FatalHelper fatalHelper;
 FatalHelper __attribute__ ((__init_priority__ (101))) fatalHelper;
 #endif
 
-}
+} // namespace
 
 SingletonVault::~SingletonVault() { destroyInstances(); }
 
@@ -105,12 +125,17 @@ void SingletonVault::registrationComplete() {
   auto state = state_.wlock();
   stateCheck(SingletonVaultState::Running, *state);
 
+  if (state->registrationComplete) {
+    return;
+  }
+
   auto singletons = singletons_.rlock();
   if (type_ == Type::Strict) {
     for (const auto& p : *singletons) {
       if (p.second->hasLiveInstance()) {
         throw std::runtime_error(
-            "Singleton created before registration was complete.");
+            "Singleton " + p.first.name() +
+            " created before registration was complete.");
       }
     }
   }
@@ -241,4 +266,4 @@ void SingletonVault::scheduleDestroyInstances() {
   static SingletonVaultDestructor singletonVaultDestructor;
 }
 
-}
+} // namespace folly