From: Michael Friedrich Date: Tue, 4 Sep 2018 13:17:34 +0000 (+0000) Subject: Fix static initializer priority for namespaces in LTO builds X-Git-Tag: v2.10.0~43^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=refs%2Fpull%2F6591%2Fhead;p=icinga2 Fix static initializer priority for namespaces in LTO builds fixes #6575 --- diff --git a/lib/base/function.hpp b/lib/base/function.hpp index 493be13ee..3eb7ce98d 100644 --- a/lib/base/function.hpp +++ b/lib/base/function.hpp @@ -72,6 +72,7 @@ private: bool side_effect_free, bool deprecated); }; +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ #define REGISTER_FUNCTION(ns, name, callback, args) \ INITIALIZE_ONCE_WITH_PRIORITY([]() { \ Function::Ptr sf = new icinga::Function(#ns "#" #name, callback, String(args).Split(":"), false); \ diff --git a/lib/base/objecttype.cpp b/lib/base/objecttype.cpp index d77bfcdae..eff6696c9 100644 --- a/lib/base/objecttype.cpp +++ b/lib/base/objecttype.cpp @@ -23,6 +23,7 @@ using namespace icinga; +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ INITIALIZE_ONCE_WITH_PRIORITY([]() { Type::Ptr type = new ObjectType(); type->SetPrototype(Object::GetPrototype()); diff --git a/lib/base/primitivetype.hpp b/lib/base/primitivetype.hpp index 45ae8411a..61cedb6cb 100644 --- a/lib/base/primitivetype.hpp +++ b/lib/base/primitivetype.hpp @@ -48,6 +48,7 @@ private: ObjectFactory m_Factory; }; +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ #define REGISTER_BUILTIN_TYPE(type, prototype) \ INITIALIZE_ONCE_WITH_PRIORITY([]() { \ icinga::Type::Ptr t = new PrimitiveType(#type, "None"); \ diff --git a/lib/base/scriptframe.cpp b/lib/base/scriptframe.cpp index 90407613e..36f75284e 100644 --- a/lib/base/scriptframe.cpp +++ b/lib/base/scriptframe.cpp @@ -29,6 +29,10 @@ boost::thread_specific_ptr > ScriptFrame::m_ScriptFram static auto l_InternalNSBehavior = new ConstNamespaceBehavior(); +/* Ensure that this gets called with highest priority + * and wins against other static initializers in lib/icinga, etc. + * LTO-enabled builds will cause trouble otherwise, see GH #6575. + */ INITIALIZE_ONCE_WITH_PRIORITY([]() { Namespace::Ptr globalNS = ScriptGlobal::GetGlobals(); @@ -51,7 +55,7 @@ INITIALIZE_ONCE_WITH_PRIORITY([]() { Namespace::Ptr internalNS = new Namespace(l_InternalNSBehavior); globalNS->SetAttribute("Internal", std::make_shared(internalNS)); -}, 50); +}, 1000); INITIALIZE_ONCE_WITH_PRIORITY([]() { l_InternalNSBehavior->Freeze(); diff --git a/lib/base/type.cpp b/lib/base/type.cpp index b8bddd7fb..a010d55a0 100644 --- a/lib/base/type.cpp +++ b/lib/base/type.cpp @@ -26,6 +26,7 @@ using namespace icinga; Type::Ptr Type::TypeInstance; +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ INITIALIZE_ONCE_WITH_PRIORITY([]() { Type::Ptr type = new TypeType(); type->SetPrototype(TypeType::GetPrototype()); diff --git a/lib/base/type.hpp b/lib/base/type.hpp index ef8ce6d23..a8fb7dc89 100644 --- a/lib/base/type.hpp +++ b/lib/base/type.hpp @@ -138,6 +138,7 @@ class TypeImpl { }; +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ #define REGISTER_TYPE(type) \ INITIALIZE_ONCE_WITH_PRIORITY([]() { \ icinga::Type::Ptr t = new TypeImpl(); \ diff --git a/lib/cli/daemonutility.cpp b/lib/cli/daemonutility.cpp index ea1630c8a..cddbf4ec5 100644 --- a/lib/cli/daemonutility.cpp +++ b/lib/cli/daemonutility.cpp @@ -21,11 +21,11 @@ #include "base/utility.hpp" #include "base/logger.hpp" #include "base/application.hpp" +#include "base/scriptglobal.hpp" #include "config/configcompiler.hpp" #include "config/configcompilercontext.hpp" #include "config/configitembuilder.hpp" - using namespace icinga; static bool ExecuteExpression(Expression *expression) @@ -146,6 +146,9 @@ bool DaemonUtility::ValidateConfigFiles(const std::vector& configs, return false; Namespace::Ptr systemNS = ScriptGlobal::Get("System"); + VERIFY(systemNS); + + /* This is initialized inside the IcingaApplication class. */ Value vAppType; VERIFY(systemNS->Get("ApplicationType", &vAppType)); diff --git a/lib/config/configfragment.hpp b/lib/config/configfragment.hpp index bd3c5939b..cbc772737 100644 --- a/lib/config/configfragment.hpp +++ b/lib/config/configfragment.hpp @@ -26,6 +26,7 @@ #include "base/exception.hpp" #include "base/application.hpp" +/* Ensure that the priority is lower than the basic namespace initialization in scriptframe.cpp. */ #define REGISTER_CONFIG_FRAGMENT(name, fragment) \ INITIALIZE_ONCE_WITH_PRIORITY([]() { \ std::unique_ptr expression = icinga::ConfigCompiler::CompileText(name, fragment); \ diff --git a/lib/icinga/icingaapplication.cpp b/lib/icinga/icingaapplication.cpp index 28ca04bbd..a8d7104b3 100644 --- a/lib/icinga/icingaapplication.cpp +++ b/lib/icinga/icingaapplication.cpp @@ -41,6 +41,7 @@ using namespace icinga; static Timer::Ptr l_RetentionTimer; REGISTER_TYPE(IcingaApplication); +/* Ensure that the priority is lower than the basic System namespace initialization in scriptframe.cpp. */ INITIALIZE_ONCE_WITH_PRIORITY(&IcingaApplication::StaticInitialize, 50); void IcingaApplication::StaticInitialize() @@ -59,11 +60,15 @@ void IcingaApplication::StaticInitialize() ScriptGlobal::Set("NodeName", node_name); - ScriptGlobal::Set("System.ApplicationType", "IcingaApplication", true); + Namespace::Ptr systemNS = ScriptGlobal::Get("System"); + /* Ensure that the System namespace is already initialized. Otherwise this is a programming error. */ + VERIFY(systemNS); - ScriptGlobal::Set("System.ApplicationVersion", Application::GetAppVersion(), true); + systemNS->Set("ApplicationType", "IcingaApplication", true); + systemNS->Set("ApplicationVersion", Application::GetAppVersion(), true); Namespace::Ptr globalNS = ScriptGlobal::GetGlobals(); + VERIFY(globalNS); auto icingaNSBehavior = new ConstNamespaceBehavior(); icingaNSBehavior->Freeze();