[icinga-checkins] icinga.org: icinga2/master: Properly shut down instances of the ScriptInterpreter class.

git at icinga.org git at icinga.org
Thu Feb 14 15:40:06 CET 2013


Module: icinga2
Branch: master
Commit: d4afb4087d8bcbb1f4b023bab11d2de45e476291
URL:    https://git.icinga.org/?p=icinga2.git;a=commit;h=d4afb4087d8bcbb1f4b023bab11d2de45e476291

Author: Gunnar Beutner <gunnar.beutner at netways.de>
Date:   Thu Feb 14 15:39:53 2013 +0100

Properly shut down instances of the ScriptInterpreter class.

---

 lib/base/script.cpp            |    4 +++
 lib/base/scriptinterpreter.cpp |   54 ++++++++++++++++++++++++++++------------
 lib/base/scriptinterpreter.h   |    8 ++++-
 3 files changed, 48 insertions(+), 18 deletions(-)

diff --git a/lib/base/script.cpp b/lib/base/script.cpp
index 0bcc5ca..c324f98 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 787ce68..028edbe 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 1a6dc10..a207376 100644
--- a/lib/base/scriptinterpreter.h
+++ b/lib/base/scriptinterpreter.h
@@ -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;
 





More information about the icinga-checkins mailing list