[conduit] Tidy DBus interface, fix hanging at exit



commit 822cf09cead327209bb71aa8530afec894eb2741
Author: John Stowers <john stowers gmail com>
Date:   Thu Sep 9 23:00:27 2010 +1200

    Tidy DBus interface, fix hanging at exit

 conduit/Conduit.py                |    9 +++++++++
 conduit/DBus.py                   |   28 +++++++++++++++++++---------
 conduit/Database.py               |    2 +-
 conduit/Main.py                   |   19 +++++++------------
 conduit/SyncSet.py                |   13 +++----------
 test/python-tests/TestCoreDBus.py |   10 +++++-----
 6 files changed, 44 insertions(+), 37 deletions(-)
---
diff --git a/conduit/Conduit.py b/conduit/Conduit.py
index 5490d77..6c27da3 100644
--- a/conduit/Conduit.py
+++ b/conduit/Conduit.py
@@ -351,3 +351,12 @@ class Conduit(gobject.GObject):
             del(self._conflicts[hc])
         except KeyError:
             log.warn("Unknown conflict")
+
+    def quit(self):
+        for dp in self.get_all_dataproviders():
+            if dp.module:
+                try:
+                    dp.module.uninitialize()
+                except Exception:
+                    log.warn("Could not uninitialize %s" % dp, exc_info=True)
+
diff --git a/conduit/DBus.py b/conduit/DBus.py
index 16684bd..5bbceb3 100644
--- a/conduit/DBus.py
+++ b/conduit/DBus.py
@@ -434,7 +434,7 @@ class SyncSetDBusItem(DBusItem):
         self.syncSet.restore_from_xml(os.path.abspath(path))
 
 class DBusInterface(DBusItem):
-    def __init__(self, conduitApplication, moduleManager, typeConverter, syncManager, guiSyncSet, dbusSyncSet):
+    def __init__(self, conduitApplication, moduleManager, typeConverter, syncManager, guiSyncSet):
         DBusItem.__init__(self, iface=APPLICATION_DBUS_IFACE, path="/")
 
         self.conduitApplication = conduitApplication
@@ -447,16 +447,14 @@ class DBusInterface(DBusItem):
         #type converter and sync manager
         self.type_converter = typeConverter
         self.sync_manager = syncManager
-
         
         #export the syncsets
-        if guiSyncSet != None:
-            new = SyncSetDBusItem(guiSyncSet, "gui")
-            EXPORTED_OBJECTS[new.get_path()] = new
+        new = SyncSetDBusItem(guiSyncSet, "gui")
+        EXPORTED_OBJECTS[new.get_path()] = new
 
-        if dbusSyncSet != None:
-            new = SyncSetDBusItem(dbusSyncSet, "dbus")
-            EXPORTED_OBJECTS[new.get_path()] = new
+        self.sync_set = SyncSet.SyncSet(moduleManager,syncManager)
+        new = SyncSetDBusItem(self.sync_set, "dbus")
+        EXPORTED_OBJECTS[new.get_path()] = new
             
         #export myself
         EXPORTED_OBJECTS[self.get_path()] = self
@@ -475,7 +473,7 @@ class DBusInterface(DBusItem):
         i = Utils.uuid_string()
         new = SyncSetDBusItem(ss, i)
         EXPORTED_OBJECTS[new.get_path()] = new
-        return new    
+        return new
     
     def _get_dataprovider(self, key):
         """
@@ -522,6 +520,18 @@ class DBusInterface(DBusItem):
     def _on_dataprovider_unavailable(self, loader, dataprovider):
         self.DataproviderUnavailable(dataprovider.get_key())
 
+    def quit(self):
+        #need to call quit() on all sync sets or conduits as they may have been 
+        #created here...
+        for path in EXPORTED_OBJECTS:
+            if path.startswith("/syncset/"):
+                EXPORTED_OBJECTS[path].syncSet.quit()
+            elif path.startswith("/conduit/"):
+                EXPORTED_OBJECTS[path].conduit.quit()
+
+    def get_syncset(self):
+        return self.sync_set
+
     @dbus.service.signal(APPLICATION_DBUS_IFACE, signature='s')
     def DataproviderAvailable(self, key):
         self._print("Emmiting DBus signal DataproviderAvailable %s" % key)
diff --git a/conduit/Database.py b/conduit/Database.py
index 4dda6d2..19efbfb 100755
--- a/conduit/Database.py
+++ b/conduit/Database.py
@@ -281,7 +281,7 @@ class ThreadSafeGenericDB(Thread, GenericDB):
         self.reqs=Queue()
         self.stopped = False
         self.start()
-        
+      
     def _open(self):
         #open the db in the thread where it is used
         pass
diff --git a/conduit/Main.py b/conduit/Main.py
index 39c1d81..6d268d9 100644
--- a/conduit/Main.py
+++ b/conduit/Main.py
@@ -42,7 +42,6 @@ class Application(dbus.service.Object):
         self.statusIcon = None
         self.dbus = None
         self.guiSyncSet = None
-        self.dbusSyncSet = None
         self.uiLib = None
 
         gobject.set_application_name("Conduit")
@@ -185,10 +184,6 @@ class Application(dbus.service.Object):
                         syncManager=conduit.GLOBALS.syncManager,
                         xmlSettingFilePath=self.settingsFile
                         )
-        self.dbusSyncSet = SyncSet(
-                    moduleManager=conduit.GLOBALS.moduleManager,
-                    syncManager=conduit.GLOBALS.syncManager
-                    )
 
         #Set the view models
         if options.build_gui:
@@ -202,13 +197,13 @@ class Application(dbus.service.Object):
                         moduleManager=conduit.GLOBALS.moduleManager,
                         typeConverter=conduit.GLOBALS.typeConverter,
                         syncManager=conduit.GLOBALS.syncManager,
-                        guiSyncSet=self.guiSyncSet,
-                        dbusSyncSet=self.dbusSyncSet
+                        guiSyncSet=self.guiSyncSet
                         )
         
         if self.statusIcon:
-            self.dbusSyncSet.connect("conduit-added", self.statusIcon.on_conduit_added)
-            self.dbusSyncSet.connect("conduit-removed", self.statusIcon.on_conduit_removed)
+            dbusSyncSet = self.dbus.get_syncset()
+            dbusSyncSet.connect("conduit-added", self.statusIcon.on_conduit_added)
+            dbusSyncSet.connect("conduit-removed", self.statusIcon.on_conduit_removed)
 
         #hide the splash screen
         self.HideSplash()
@@ -287,9 +282,9 @@ class Application(dbus.service.Object):
         #unitialize all dataproviders
         log.info("Unitializing dataproviders")
         self.guiSyncSet.quit()
-        log.info("GUI Quit")
-        self.dbusSyncSet.quit()
-        log.info("DBus Quit")
+
+        log.info("Closing DBus interface")
+        self.dbus.quit()
 
         #Save the mapping DB
         conduit.GLOBALS.mappingDB.save()
diff --git a/conduit/SyncSet.py b/conduit/SyncSet.py
index b375dcb..daf85de 100644
--- a/conduit/SyncSet.py
+++ b/conduit/SyncSet.py
@@ -46,14 +46,6 @@ class SyncSet(gobject.GObject):
         # FIXME: temporary hack - need to let factories know about this factory :-\!
         self.moduleManager.emit("syncset-added", self)
         
-    def _unitialize_dataproviders(self, cond):
-        for dp in cond.get_all_dataproviders():
-            if dp.module:
-                try:
-                    dp.module.uninitialize()
-                except Exception:
-                    log.warn("Could not uninitialize %s" % dp, exc_info=True)
-                
     def _restore_dataprovider(self, cond, wrapperKey, dpName="", dpxml="", trySourceFirst=True):
         """
         Adds the dataprovider back onto the canvas at the specifed
@@ -107,7 +99,7 @@ class SyncSet(gobject.GObject):
 
     def remove_conduit(self, cond):
         self.emit("conduit-removed", cond)
-        self._unitialize_dataproviders(cond)
+        cond.quit()
         self.conduits.remove(cond)
 
     def get_all_conduits(self):
@@ -273,5 +265,6 @@ class SyncSet(gobject.GObject):
         Calls unitialize on all dataproviders
         """
         for c in self.conduits:
-            self._unitialize_dataproviders(c)
+            c.quit()
+
 
diff --git a/test/python-tests/TestCoreDBus.py b/test/python-tests/TestCoreDBus.py
index 1f055ad..64cde2f 100644
--- a/test/python-tests/TestCoreDBus.py
+++ b/test/python-tests/TestCoreDBus.py
@@ -2,10 +2,10 @@
 from common import *
 from conduit.DBus import *
 
-skip("FIXME: Hangs")
-
 import tempfile
 
+import threading
+
 #Call the DBus functions directly so that we get code coverage analysis
 #See example-dbus-conduit-client.py file for and example of the DBus iface
 #Note: A few small hacks are needed to acomplish this, get_path() and SENDER
@@ -19,13 +19,12 @@ def get_dbus_object(path):
     return EXPORTED_OBJECTS[path]
 
 test = SimpleTest()
-DBusInterface(
+dbi = DBusInterface(
         conduitApplication=None,
         moduleManager=test.model,
         typeConverter=test.type_converter,
         syncManager=test.sync_manager,
-        guiSyncSet=test.sync_set,
-        dbusSyncSet=None)
+        guiSyncSet=test.sync_set)
         
 dbus = get_dbus_object("/")
 
@@ -120,5 +119,6 @@ ss3 = dbus.NewSyncSet()
 ss3.RestoreFromXml(xmlfile)
 ok("Restore SyncSet from xml", True)
 
+dbi.quit()
 test.finished()
 finished()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]