]> granicus.if.org Git - icinga2/commitdiff
Run INITIALIZE_ONCE() after static initializers.
authorGunnar Beutner <gunnar@beutner.name>
Sat, 3 May 2014 23:34:53 +0000 (01:34 +0200)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 8 May 2014 07:13:04 +0000 (09:13 +0200)
Refs #6107

lib/base/initialize.h
lib/base/utility.cpp
lib/base/utility.h

index 83bf4bddc44f9642b551bff1c5e2d0df73e58056..43120c06819436fcfb74d66384f0722502a96333 100644 (file)
@@ -21,6 +21,7 @@
 #define INITIALIZE_H
 
 #include "base/i2-base.h"
+#include "base/utility.h"
 
 namespace icinga
 {
@@ -29,7 +30,10 @@ typedef void (*InitializeFunc)(void);
 
 inline bool InitializeOnceHelper(InitializeFunc func)
 {
-       func();
+       if (Utility::GetLoadingLibrary())
+               Utility::AddDeferredInitializer(func);
+       else
+               func();
 
        return true;
 }
index 71ae2d7a033ca419e3eef014b66b688b558c5bb4..9901b61f599b17749399c098dbd5f0ca0e1f855f 100644 (file)
@@ -42,6 +42,8 @@ using namespace icinga;
 
 boost::thread_specific_ptr<String> Utility::m_ThreadName;
 boost::thread_specific_ptr<unsigned int> Utility::m_RandSeed;
+boost::thread_specific_ptr<bool> Utility::m_LoadingLibrary;
+boost::thread_specific_ptr<std::vector<boost::function<void(void)> > > Utility::m_DeferredInitializers;
 
 /**
  * Demangles a symbol name.
@@ -368,8 +370,20 @@ Utility::LoadExtensionLibrary(const String& library)
 
        Log(LogInformation, "base", "Loading library '" + path + "'");
 
+       m_DeferredInitializers.reset(new std::vector<boost::function<void(void)> >());
+
 #ifdef _WIN32
-       HMODULE hModule = LoadLibrary(path.CStr());
+       HMODULE hModule;
+       
+       try {
+               SetLoadingLibrary(true);
+               hModule = LoadLibrary(path.CStr());
+       } catch (...) {
+               SetLoadingLibrary(false);
+               throw;
+       }
+
+       SetLoadingLibrary(false);
 
        if (hModule == NULL) {
                BOOST_THROW_EXCEPTION(win32_error()
@@ -378,16 +392,47 @@ Utility::LoadExtensionLibrary(const String& library)
                    << boost::errinfo_file_name(path));
        }
 #else /* _WIN32 */
-       void *hModule = dlopen(path.CStr(), RTLD_NOW);
+       void *hModule;
+       
+       try {
+               hModule = dlopen(path.CStr(), RTLD_NOW);
+       } catch (...) {
+               SetLoadingLibrary(false);
+               throw;
+       }
+
+       SetLoadingLibrary(false);
 
        if (hModule == NULL) {
                BOOST_THROW_EXCEPTION(std::runtime_error("Could not load library '" + path + "': " + dlerror()));
        }
 #endif /* _WIN32 */
 
+       BOOST_FOREACH(const boost::function<void(void)>& callback, *m_DeferredInitializers.get())
+               callback();
+
+       m_DeferredInitializers.reset();
+
        return hModule;
 }
 
+bool Utility::GetLoadingLibrary(void)
+{
+       bool *loading = m_LoadingLibrary.get();
+       return loading && *loading;
+}
+
+void Utility::SetLoadingLibrary(bool loading)
+{
+       bool *ploading = new bool(loading);
+       m_LoadingLibrary.reset(ploading);
+}
+
+void Utility::AddDeferredInitializer(const boost::function<void(void)>& callback)
+{
+       m_DeferredInitializers.get()->push_back(callback);
+}
+
 /**
  * Generates a new unique ID.
  *
index f8c05a5fe930af6b28eb33235feefb7c960b47b2..c12253e61f547c85e5f60c1478e2c95e74364d5e 100644 (file)
@@ -97,6 +97,10 @@ public:
 #endif /* _WIN32 */
        LoadExtensionLibrary(const String& library);
 
+       static bool GetLoadingLibrary(void);
+       static void SetLoadingLibrary(bool loading);
+       static void AddDeferredInitializer(const boost::function<void(void)>& callback);
+
 #ifndef _WIN32
        static void SetNonBlocking(int fd);
        static void SetCloExec(int fd);
@@ -125,6 +129,8 @@ private:
 
        static boost::thread_specific_ptr<String> m_ThreadName;
        static boost::thread_specific_ptr<unsigned int> m_RandSeed;
+       static boost::thread_specific_ptr<bool> m_LoadingLibrary;
+       static boost::thread_specific_ptr<std::vector<boost::function<void(void)> > > m_DeferredInitializers;
 };
 
 }