diff --git a/lib/remote/apilistener-filesync.cpp b/lib/remote/apilistener-filesync.cpp index 87aae6104..411028630 100644 --- a/lib/remote/apilistener-filesync.cpp +++ b/lib/remote/apilistener-filesync.cpp @@ -15,6 +15,8 @@ using namespace icinga; REGISTER_APIFUNCTION(Update, config, &ApiListener::ConfigUpdateHandler); +boost::mutex ApiListener::m_ConfigSyncStageLock; + void ApiListener::ConfigGlobHandler(ConfigDirInformation& config, const String& path, const String& file) { CONTEXT("Creating config update for file '" + file + "'"); @@ -274,6 +276,11 @@ Value ApiListener::ConfigUpdateHandler(const MessageOrigin::Ptr& origin, const D return Empty; } + /* Only one transaction is allowed, concurrent message handlers need to wait. + * This affects two parent endpoints sending the config in the same moment. + */ + boost::mutex::scoped_lock lock(m_ConfigSyncStageLock); + Log(LogInformation, "ApiListener") << "Applying config update from endpoint '" << origin->FromClient->GetEndpoint()->GetName() << "' of zone '" << GetFromZoneName(origin->FromZone) << "'."; diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index 5818ec994..022ad8281 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -165,6 +165,8 @@ private: void RemoveStatusFile(); /* filesync */ + static boost::mutex m_ConfigSyncStageLock; + static ConfigDirInformation LoadConfigDir(const String& dir); static Dictionary::Ptr MergeConfigUpdate(const ConfigDirInformation& config); static bool UpdateConfigDir(const ConfigDirInformation& oldConfig, const ConfigDirInformation& newConfig, const String& configDir, bool authoritative);