diff --git a/lib/remote/apilistener-filesync.cpp b/lib/remote/apilistener-filesync.cpp index 4371a826c..ab1d5c728 100644 --- a/lib/remote/apilistener-filesync.cpp +++ b/lib/remote/apilistener-filesync.cpp @@ -10,9 +10,11 @@ #include "base/convert.hpp" #include "base/application.hpp" #include "base/exception.hpp" +#include "base/shared.hpp" #include "base/utility.hpp" #include #include +#include using namespace icinga; @@ -310,10 +312,16 @@ Value ApiListener::ConfigUpdateHandler(const MessageOrigin::Ptr& origin, const D return Empty; } + std::thread([origin, params]() { HandleConfigUpdate(origin, params); }).detach(); + return Empty; +} + +void ApiListener::HandleConfigUpdate(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params) +{ /* 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); + auto lock (Shared::Make(m_ConfigSyncStageLock)); String apiZonesStageDir = GetApiZonesStageDir(); String fromEndpointName = origin->FromClient->GetEndpoint()->GetName(); @@ -521,14 +529,12 @@ Value ApiListener::ConfigUpdateHandler(const MessageOrigin::Ptr& origin, const D Log(LogInformation, "ApiListener") << "Received configuration updates (" << count << ") from endpoint '" << fromEndpointName << "' are different to production, triggering validation and reload."; - AsyncTryActivateZonesStage(relativePaths); + AsyncTryActivateZonesStage(relativePaths, lock); } else { Log(LogInformation, "ApiListener") << "Received configuration updates (" << count << ") from endpoint '" << fromEndpointName << "' do not qualify for production, not triggering reload."; } - - return Empty; } /** @@ -612,7 +618,7 @@ void ApiListener::TryActivateZonesStageCallback(const ProcessResult& pr, * * @param relativePaths Required for later file operations in the callback. Provides the zone name plus path in a list. */ -void ApiListener::AsyncTryActivateZonesStage(const std::vector& relativePaths) +void ApiListener::AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared::Ptr& lock) { VERIFY(Application::GetArgC() >= 1); @@ -638,7 +644,10 @@ void ApiListener::AsyncTryActivateZonesStage(const std::vector& relative Process::Ptr process = new Process(Process::PrepareCommand(args)); process->SetTimeout(Application::GetReloadTimeout()); - process->Run(std::bind(&TryActivateZonesStageCallback, _1, relativePaths)); + + process->Run([relativePaths, lock](const ProcessResult& pr) { + TryActivateZonesStageCallback(pr, relativePaths); + }); } /** diff --git a/lib/remote/apilistener.hpp b/lib/remote/apilistener.hpp index ecbeed415..e61df2c47 100644 --- a/lib/remote/apilistener.hpp +++ b/lib/remote/apilistener.hpp @@ -83,6 +83,7 @@ public: /* filesync */ static Value ConfigUpdateHandler(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); + static void HandleConfigUpdate(const MessageOrigin::Ptr& origin, const Dictionary::Ptr& params); /* configsync */ static void ConfigUpdateObjectHandler(const ConfigObject::Ptr& object, const Value& cookie); @@ -191,7 +192,7 @@ private: static void TryActivateZonesStageCallback(const ProcessResult& pr, const std::vector& relativePaths); - static void AsyncTryActivateZonesStage(const std::vector& relativePaths); + static void AsyncTryActivateZonesStage(const std::vector& relativePaths, const Shared::Ptr& lock); static String GetChecksum(const String& content); static bool CheckConfigChange(const ConfigDirInformation& oldConfig, const ConfigDirInformation& newConfig);