]> granicus.if.org Git - icinga2/commitdiff
Properly shut down instances of the ScriptInterpreter class.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 14 Feb 2013 14:39:53 +0000 (15:39 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 14 Feb 2013 14:39:53 +0000 (15:39 +0100)
lib/base/script.cpp
lib/base/scriptinterpreter.cpp
lib/base/scriptinterpreter.h

index 0bcc5ca77380f50c63f74b60e7883d2652a1b067..c324f98288be47f781cbbe7f243f0f538d5ffd93 100644 (file)
@@ -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();
 }
index 787ce6883455fe8af1a40ae0354d7a6fbae89107..028edbed15918fa967a9d6b5ccbedb08e5e4fe2f 100644 (file)
 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)
index 1a6dc10ec870e3f9743209d025867cc48bd9c828..a207376dd7a95d1605802265b9fd4b24eab76b45 100644 (file)
@@ -41,19 +41,23 @@ public:
        typedef shared_ptr<ScriptInterpreter> Ptr;
        typedef weak_ptr<ScriptInterpreter> 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<ScriptCall> m_Calls;
        condition_variable m_CallAvailable;