From: Gunnar Beutner Date: Thu, 14 Feb 2013 14:39:53 +0000 (+0100) Subject: Properly shut down instances of the ScriptInterpreter class. X-Git-Tag: v0.0.2~414 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d4afb4087d8bcbb1f4b023bab11d2de45e476291;p=icinga2 Properly shut down instances of the ScriptInterpreter class. --- diff --git a/lib/base/script.cpp b/lib/base/script.cpp index 0bcc5ca77..c324f9828 100644 --- a/lib/base/script.cpp +++ b/lib/base/script.cpp @@ -57,6 +57,10 @@ void Script::SpawnInterpreter(void) { Logger::Write(LogInformation, "base", "Reloading script '" + GetName() + "'"); + if (m_Interpreter) + m_Interpreter->Stop(); + ScriptLanguage::Ptr language = ScriptLanguage::GetByName(GetLanguage()); m_Interpreter = language->CreateInterpreter(GetSelf()); + m_Interpreter->Start(); } diff --git a/lib/base/scriptinterpreter.cpp b/lib/base/scriptinterpreter.cpp index 787ce6883..028edbed1 100644 --- a/lib/base/scriptinterpreter.cpp +++ b/lib/base/scriptinterpreter.cpp @@ -22,37 +22,59 @@ using namespace icinga; ScriptInterpreter::ScriptInterpreter(const Script::Ptr& script) - : m_Thread(&ScriptInterpreter::ThreadWorkerProc, this) +{ } + +ScriptInterpreter::~ScriptInterpreter(void) { - m_Thread.detach(); + Stop(); } -void ScriptInterpreter::ThreadWorkerProc(void) +void ScriptInterpreter::Start(void) { - ScriptCall call; + /* We can't start the thread in the constructor because + * the worker thread might end up calling one of the virtual + * methods before the object is fully constructed. */ - while (WaitForCall(&call)) - ProcessCall(call); + m_Thread = boost::thread(&ScriptInterpreter::ThreadWorkerProc, this); } -void ScriptInterpreter::EnqueueCall(const ScriptCall& call) +void ScriptInterpreter::Stop(void) { - boost::mutex::scoped_lock lock(m_Mutex); - m_Calls.push_back(call); - m_CallAvailable.notify_all(); + { + boost::mutex::scoped_lock lock(m_Mutex); + + if (m_Shutdown) + return; + + m_Shutdown = true; + m_CallAvailable.notify_all(); + } + + m_Thread.join(); } -bool ScriptInterpreter::WaitForCall(ScriptCall *call) +void ScriptInterpreter::ThreadWorkerProc(void) { boost::mutex::scoped_lock lock(m_Mutex); - while (m_Calls.empty()) - m_CallAvailable.wait(lock); + for (;;) { + while (m_Calls.empty() && !m_Shutdown) + m_CallAvailable.wait(lock); + + if (m_Shutdown) + break; - *call = m_Calls.front(); - m_Calls.pop_front(); + ScriptCall call = m_Calls.front(); + m_Calls.pop_front(); + } +} - return true; + +void ScriptInterpreter::EnqueueCall(const ScriptCall& call) +{ + boost::mutex::scoped_lock lock(m_Mutex); + m_Calls.push_back(call); + m_CallAvailable.notify_all(); } void ScriptInterpreter::RegisterMethod(const String& name) diff --git a/lib/base/scriptinterpreter.h b/lib/base/scriptinterpreter.h index 1a6dc10ec..a207376dd 100644 --- a/lib/base/scriptinterpreter.h +++ b/lib/base/scriptinterpreter.h @@ -41,19 +41,23 @@ public: typedef shared_ptr Ptr; typedef weak_ptr WeakPtr; + ~ScriptInterpreter(void); + void EnqueueCall(const ScriptCall& call); + void Start(void); + void Stop(void); + protected: ScriptInterpreter(const Script::Ptr& script); virtual void ProcessCall(const ScriptCall& call) = 0; - bool WaitForCall(ScriptCall *call); - void RegisterMethod(const String& name); private: boost::mutex m_Mutex; + bool m_Shutdown; deque m_Calls; condition_variable m_CallAvailable;