From: Gunnar Beutner Date: Sat, 3 May 2014 23:34:53 +0000 (+0200) Subject: Run INITIALIZE_ONCE() after static initializers. X-Git-Tag: v0.0.11~77 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0571d8a46498b5d3671bd97d89e0c445e1f2b8db;p=icinga2 Run INITIALIZE_ONCE() after static initializers. Refs #6107 --- diff --git a/lib/base/initialize.h b/lib/base/initialize.h index 83bf4bddc..43120c068 100644 --- a/lib/base/initialize.h +++ b/lib/base/initialize.h @@ -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; } diff --git a/lib/base/utility.cpp b/lib/base/utility.cpp index 71ae2d7a0..9901b61f5 100644 --- a/lib/base/utility.cpp +++ b/lib/base/utility.cpp @@ -42,6 +42,8 @@ using namespace icinga; boost::thread_specific_ptr Utility::m_ThreadName; boost::thread_specific_ptr Utility::m_RandSeed; +boost::thread_specific_ptr Utility::m_LoadingLibrary; +boost::thread_specific_ptr > > 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 >()); + #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& 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& callback) +{ + m_DeferredInitializers.get()->push_back(callback); +} + /** * Generates a new unique ID. * diff --git a/lib/base/utility.h b/lib/base/utility.h index f8c05a5fe..c12253e61 100644 --- a/lib/base/utility.h +++ b/lib/base/utility.h @@ -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& callback); + #ifndef _WIN32 static void SetNonBlocking(int fd); static void SetCloExec(int fd); @@ -125,6 +129,8 @@ private: static boost::thread_specific_ptr m_ThreadName; static boost::thread_specific_ptr m_RandSeed; + static boost::thread_specific_ptr m_LoadingLibrary; + static boost::thread_specific_ptr > > m_DeferredInitializers; }; }