diff --git a/src/virtManager/baseclass.py b/src/virtManager/baseclass.py index fc6d1a78b..c0ea477ed 100644 --- a/src/virtManager/baseclass.py +++ b/src/virtManager/baseclass.py @@ -42,6 +42,9 @@ class vmmGObject(gobject.GObject): self._gobject_timeouts = [] self._gconf_handles = [] + self._object_key = str(self) + self.config.add_object(self._object_key) + def cleanup(self): # Do any cleanup required to drop reference counts so object is # actually reaped by python. Usually means unregistering callbacks @@ -81,6 +84,14 @@ class vmmGObject(gobject.GObject): from virtManager import halhelper return halhelper.get_hal_helper() + def __del__(self): + if hasattr(gobject.GObject, "__del__"): + getattr(gobject.GObject, "__del__")(self) + + try: + self.config.remove_object(self._object_key) + except: + logging.exception("Error removing %s" % self._object_key) class vmmGObjectUI(vmmGObject): def __init__(self, filename, windowname): diff --git a/src/virtManager/config.py b/src/virtManager/config.py index 39761ef40..20fc8acc4 100644 --- a/src/virtManager/config.py +++ b/src/virtManager/config.py @@ -115,6 +115,8 @@ class vmmConfig(object): self.hv_packages = [] self.libvirt_packages = [] + self._objects = [] + self.status_icons = { libvirt.VIR_DOMAIN_BLOCKED: gtk.gdk.pixbuf_new_from_file_at_size(self.get_icon_dir() + "/state_running.png", 18, 18), libvirt.VIR_DOMAIN_CRASHED: gtk.gdk.pixbuf_new_from_file_at_size(self.get_icon_dir() + "/state_crashed.png", 18, 18), @@ -179,6 +181,15 @@ class vmmConfig(object): def remove_notifier(self, h): self.conf.notify_remove(h) + # Used for debugging reference leaks, we keep track of all objects + # come and go so we can do a leak report at app shutdown + def add_object(self, obj): + self._objects.append(obj) + def remove_object(self, obj): + self._objects.remove(obj) + def get_objects(self): + return self._objects[:] + # Per-VM/Connection/Connection Host Option dealings def _perconn_helper(self, uri, pref_func, func_type, value=None): suffix = "connection_prefs/%s" % gconf.escape_key(uri, len(uri)) diff --git a/src/virtManager/engine.py b/src/virtManager/engine.py index 707dd3d5c..1135a9be4 100644 --- a/src/virtManager/engine.py +++ b/src/virtManager/engine.py @@ -47,6 +47,9 @@ from virtManager.error import vmmErrorDialog from virtManager.systray import vmmSystray import virtManager.util as util +# Enable this to get a report of leaked objects on app shutdown +debug_ref_leaks = False + def default_uri(): tryuri = None if os.path.exists("/var/lib/xend") and os.path.exists("/proc/xen"): @@ -473,6 +476,12 @@ class vmmEngine(vmmGObject): conns = self.connections.values() for conn in conns: conn["connection"].close() + self.connections = {} + + if debug_ref_leaks: + for name in self.config.get_objects(): + logging.debug("Leaked %s" % name) + logging.debug("Exiting app normally.") gtk.main_quit()