diff --git a/lib/base/process.cpp b/lib/base/process.cpp index 97754c19e..aa057830d 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -49,7 +49,8 @@ static boost::once_flag l_ProcessOnceFlag = BOOST_ONCE_INIT; static boost::once_flag l_SpawnHelperOnceFlag = BOOST_ONCE_INIT; Process::Process(Process::Arguments arguments, Dictionary::Ptr extraEnvironment) - : m_Arguments(std::move(arguments)), m_ExtraEnvironment(std::move(extraEnvironment)), m_Timeout(600), m_AdjustPriority(false) + : m_Arguments(std::move(arguments)), m_ExtraEnvironment(std::move(extraEnvironment)), + m_Timeout(600), m_AdjustPriority(false), m_ResultAvailable(false) #ifdef _WIN32 , m_ReadPending(false), m_ReadFailed(false), m_Overlapped() #endif /* _WIN32 */ @@ -1007,6 +1008,12 @@ void Process::Run(const std::function& callback) #endif /* _WIN32 */ } +const ProcessResult& Process::WaitForResult() { + std::unique_lock lock(m_ResultMutex); + m_ResultCondition.wait(lock, [this]{ return m_ResultAvailable; }); + return m_Result; +} + bool Process::DoEvents() { bool is_timeout = false; @@ -1114,10 +1121,15 @@ bool Process::DoEvents() } #endif /* _WIN32 */ - m_Result.PID = m_PID; - m_Result.ExecutionEnd = Utility::GetTime(); - m_Result.ExitStatus = exitcode; - m_Result.Output = output; + { + std::lock_guard lock(m_ResultMutex); + m_Result.PID = m_PID; + m_Result.ExecutionEnd = Utility::GetTime(); + m_Result.ExitStatus = exitcode; + m_Result.Output = output; + m_ResultAvailable = true; + } + m_ResultCondition.notify_all(); if (m_Callback) Utility::QueueAsyncCallback(std::bind(m_Callback, m_Result)); diff --git a/lib/base/process.hpp b/lib/base/process.hpp index 7fbfe0ac0..53ee2bb5b 100644 --- a/lib/base/process.hpp +++ b/lib/base/process.hpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include namespace icinga { @@ -61,6 +63,8 @@ public: void Run(const std::function& callback = std::function()); + const ProcessResult& WaitForResult(); + pid_t GetPID() const; static Arguments PrepareCommand(const Value& command); @@ -94,6 +98,9 @@ private: std::ostringstream m_OutputStream; std::function m_Callback; ProcessResult m_Result; + bool m_ResultAvailable; + std::mutex m_ResultMutex; + std::condition_variable m_ResultCondition; static void IOThreadProc(int tid); bool DoEvents();