diff --git a/lib/remote/configobjectutility.cpp b/lib/remote/configobjectutility.cpp index 9b5cf88b5ac..4c75459a660 100644 --- a/lib/remote/configobjectutility.cpp +++ b/lib/remote/configobjectutility.cpp @@ -2,7 +2,6 @@ #include "remote/configobjectutility.hpp" #include "remote/configpackageutility.hpp" -#include "remote/apilistener.hpp" #include "config/configcompiler.hpp" #include "config/configitem.hpp" #include "base/atomic-file.hpp" @@ -19,6 +18,8 @@ using namespace icinga; +ObjectNameMutex ConfigObjectUtility::m_ObjectCreateMutex; + String ConfigObjectUtility::GetConfigDir() { String prefix = ConfigPackageUtility::GetPackageDir() + "/_api/"; @@ -181,6 +182,13 @@ bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& full { CreateStorage(); + // Lock the object name of the given type to prevent from being created concurrently. + m_ObjectCreateMutex.Lock(type, fullName); + + Defer unlockAndNotify([&type, &fullName]{ + m_ObjectCreateMutex.Unlock(type, fullName); + }); + { auto configType (dynamic_cast(type.get())); diff --git a/lib/remote/configobjectutility.hpp b/lib/remote/configobjectutility.hpp index 5a113c82edd..f3d4f0257ff 100644 --- a/lib/remote/configobjectutility.hpp +++ b/lib/remote/configobjectutility.hpp @@ -3,6 +3,7 @@ #ifndef CONFIGOBJECTUTILITY_H #define CONFIGOBJECTUTILITY_H +#include "remote/apilistener.hpp" #include "remote/i2-remote.hpp" #include "base/array.hpp" #include "base/configobject.hpp" @@ -40,6 +41,9 @@ class ConfigObjectUtility static String EscapeName(const String& name); static bool DeleteObjectHelper(const ConfigObject::Ptr& object, bool cascade, const Array::Ptr& errors, const Array::Ptr& diagnosticInformation, const Value& cookie = Empty); + + // Ensures that an object is being created exclusively by one thread at any given time. + static ObjectNameMutex m_ObjectCreateMutex; }; }