← Back to team overview

zeitgeist team mailing list archive

[Merge] lp:~thekorn/zeitgeist/handle-SIGHUP into lp:zeitgeist

 

Markus Korn has proposed merging lp:~thekorn/zeitgeist/handle-SIGHUP into lp:zeitgeist.

Requested reviews:
  Zeitgeist Framework Team (zeitgeist)


Added a way to shutdown the zeitgeist-daemon in a clean way by sending a SIGHUP signal to the process (as described in [0])

[0] http://lists.zeitgeist-project.com/pipermail/dev/2010-September/000157.html
-- 
https://code.launchpad.net/~thekorn/zeitgeist/handle-SIGHUP/+merge/35539
Your team Zeitgeist Framework Team is requested to review the proposed merge of lp:~thekorn/zeitgeist/handle-SIGHUP into lp:zeitgeist.
=== modified file '_zeitgeist/engine/main.py'
--- _zeitgeist/engine/main.py	2010-09-02 08:44:39 +0000
+++ _zeitgeist/engine/main.py	2010-09-15 14:26:38 +0000
@@ -130,6 +130,7 @@
 		return self.__extensions
 	
 	def close(self):
+		log.debug("closing down the zeitgeist engine ...")
 		self.extensions.unload()
 		self._cursor.connection.close()
 		self._cursor = None

=== modified file '_zeitgeist/engine/remote.py'
--- _zeitgeist/engine/remote.py	2010-09-09 21:40:51 +0000
+++ _zeitgeist/engine/remote.py	2010-09-15 14:26:38 +0000
@@ -345,6 +345,7 @@
 		"""Terminate the running Zeitgeist engine process; use with caution,
 		this action must only be triggered with the user's explicit consent,
 		as it will affect all applications using Zeitgeist"""
+		self._engine.close()
 		if self._mainloop:
 			self._mainloop.quit()
 	

=== modified file '_zeitgeist/singleton.py'
--- _zeitgeist/singleton.py	2010-01-23 21:37:08 +0000
+++ _zeitgeist/singleton.py	2010-09-15 14:26:38 +0000
@@ -40,7 +40,7 @@
 		
 		if dbus_service.NameHasOwner(ZeitgeistDBusInterface.BUS_NAME):
 			# already running daemon instance
-			if _config.options.replace or _config.options.quit:
+			if hasattr(_config, "options") and (_config.options.replace or _config.options.quit):
 				if _config.options.quit:
 					logging.info("Stopping the currently running instance.")
 				else:
@@ -58,13 +58,13 @@
 					("An existing instance was found. Please use "
 					 "--replace to quit it and start a new instance.")
 				)
-		elif _config.options.quit:
+		elif hasattr(_config, "options") and _config.options.quit:
 			logging.info("There is no running instance; doing nothing.")
 		else:
 			# service is not running, save to start
 			logging.debug("No running instances found.")
 		
-		if _config.options.quit:
+		if hasattr(_config, "options") and _config.options.quit:
 			sys.exit(0)
 		
 		bus = dbus.service.BusName(ZeitgeistDBusInterface.BUS_NAME, sbus, do_not_queue=True)

=== modified file 'doc/zeitgeist-daemon.1'
--- doc/zeitgeist-daemon.1	2010-05-26 16:34:39 +0000
+++ doc/zeitgeist-daemon.1	2010-09-15 14:26:38 +0000
@@ -71,6 +71,9 @@
 The ZEITGEIST_DEFAULT_EXTENSIONS and the ZEITGEIST_EXTRA_EXTENSIONS
 variable require a no-space comma separated list of module.class names.
 
+.SH SIGNALS
+\fISIGHUP\f1: zeitgeist\-daemon will shut itself down in a clean way.
+
 .SH EXAMPLES
 .PP
 .B environment variables

=== modified file 'test/remote-test.py'
--- test/remote-test.py	2010-08-02 13:15:11 +0000
+++ test/remote-test.py	2010-09-15 14:26:38 +0000
@@ -4,6 +4,9 @@
 import os
 import sys
 import logging
+import signal
+import time
+from subprocess import Popen, PIPE
 
 # DBus setup
 import gobject
@@ -15,6 +18,7 @@
 from zeitgeist.client import ZeitgeistDBusInterface, ZeitgeistClient
 from zeitgeist.datamodel import (Event, Subject, Interpretation, Manifestation,
 	TimeRange, StorageState)
+from _zeitgeist.engine.remote import RemoteInterface
 
 import testutils
 from testutils import parse_events
@@ -315,6 +319,34 @@
 		iface = self.client._iface # we know that client._iface is as clean as possible
 		registry = iface.get_extension("DataSourceRegistry", "data_source_registry")
 		registry.GetDataSources()
+		
+class ZeitgeistRemoteInterfaceTest(unittest.TestCase):
+	
+	def testQuit(self):
+		"""calling Quit() on the remote interface should shutdown the
+		engine in a clean way"""
+		interface = RemoteInterface()
+		self.assertEquals(interface._engine.is_closed(), False)
+		interface.Quit()
+		self.assertEquals(interface._engine.is_closed(), True)
+		
+class ZeitgeistDaemonTest(unittest.TestCase):
+	
+	def testSIGHUP(self):
+		"""sending a SIGHUP signal to a running deamon instance results
+		in a clean shutdown"""
+		daemon = Popen(
+			["./zeitgeist-daemon.py", "--no-datahub"], stderr=PIPE, stdout=PIPE
+		)
+		# give the daemon some time to wake up
+		time.sleep(3)
+		err = daemon.poll()
+		if err:
+			raise RuntimeError("Could not start daemon,  got err=%i" % err)
+		os.kill(daemon.pid, signal.SIGHUP)
+		err = daemon.wait()
+		self.assertEqual(err, 0)
+		
 	
 if __name__ == "__main__":
 	unittest.main()

=== modified file 'zeitgeist-daemon.py'
--- zeitgeist-daemon.py	2010-08-02 20:46:47 +0000
+++ zeitgeist-daemon.py	2010-09-15 14:26:38 +0000
@@ -26,6 +26,7 @@
 import gettext
 import logging
 import optparse
+import signal
 from copy import copy
 
 # Make sure we can find the private _zeitgeist namespace
@@ -94,7 +95,7 @@
 mainloop = gobject.MainLoop()
 
 try:
-	RemoteInterface(mainloop = mainloop)
+	interface = RemoteInterface(mainloop = mainloop)
 except RuntimeError, e:
 	logging.error(unicode(e))
 	sys.exit(1)
@@ -110,5 +111,11 @@
 		logging.warning(
 			_("File \"%s\" not found, not starting datahub") % passive_loggers)
 
+def handle_sighup(signum, frame):
+	"""We are using the SIGHUP signal to shutdown zeitgeist in a clean way"""
+	logging.info("got SIGHUP signal, shutting down zeitgeist interface")
+	interface.Quit()
+signal.signal(signal.SIGHUP, handle_sighup)
+
 logging.info(_(u"Starting Zeitgeist service..."))
 mainloop.run()