mirror of
https://github.com/virt-manager/virt-manager.git
synced 2024-10-27 01:55:20 +03:00
domain: Fix ref count issues preventing proper cleanup
Make sure we unregister all callbacks so that the domain object is properly reaped by python. Mediadev has somewhat similar issues, so handle that.
This commit is contained in:
parent
f5464b606d
commit
586f7b3274
@ -19,6 +19,8 @@
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
import logging
|
||||
|
||||
import gtk
|
||||
import gobject
|
||||
@ -36,10 +38,50 @@ class vmmGObject(gobject.GObject):
|
||||
gobject.GObject.__init__(self)
|
||||
self.config = virtManager.config.running_config
|
||||
|
||||
self._gobject_handles = []
|
||||
self._gobject_timeouts = []
|
||||
self._gconf_handles = []
|
||||
|
||||
def cleanup(self):
|
||||
# Do any cleanup required to drop reference counts so object is
|
||||
# actually reaped by python. Usually means unregistering callbacks
|
||||
try:
|
||||
for h in self._gconf_handles[:]:
|
||||
self.remove_gconf_handle(h)
|
||||
for h in self._gobject_handles[:]:
|
||||
self.remove_gobject_handle(h)
|
||||
for h in self._gobject_timeouts[:]:
|
||||
self.remove_gobject_timeout(h)
|
||||
except:
|
||||
logging.exception("Error cleaning up %s" % self)
|
||||
|
||||
def add_gconf_handle(self, handle):
|
||||
self._gconf_handles.append(handle)
|
||||
def remove_gconf_handle(self, handle):
|
||||
self.config.remove_notifier(handle)
|
||||
self._gconf_handles.remove(handle)
|
||||
|
||||
def add_gobject_handle(self, handle):
|
||||
self._gobject_handles.append(handle)
|
||||
def remove_gobject_handle(self, handle):
|
||||
self.disconnect(handle)
|
||||
self._gobject_handles.remove(handle)
|
||||
|
||||
def add_gobject_timeout(self, handle):
|
||||
self._gobject_timeouts.append(handle)
|
||||
def remove_gobject_timeout(self, handle):
|
||||
gobject.source_remove(handle)
|
||||
self._gobject_timeouts.remove(handle)
|
||||
|
||||
def refcount(self):
|
||||
# Function generates 2 temporary refs, so adjust total accordingly
|
||||
return (sys.getrefcount(self) - 2)
|
||||
|
||||
def get_hal_helper(self):
|
||||
from virtManager import halhelper
|
||||
return halhelper.get_hal_helper()
|
||||
|
||||
|
||||
class vmmGObjectUI(vmmGObject):
|
||||
def __init__(self, filename, windowname):
|
||||
vmmGObject.__init__(self)
|
||||
|
@ -176,6 +176,9 @@ class vmmConfig(object):
|
||||
ret.append("spice")
|
||||
return ret
|
||||
|
||||
def remove_notifier(self, h):
|
||||
self.conf.notify_remove(h)
|
||||
|
||||
# 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))
|
||||
@ -436,11 +439,11 @@ class vmmConfig(object):
|
||||
self.conf.set_bool(self.conf_dir + "/stats/enable-net-poll", val)
|
||||
|
||||
def on_stats_enable_disk_poll_changed(self, cb, userdata=None):
|
||||
self.conf.notify_add(self.conf_dir + "/stats/enable-disk-poll", cb,
|
||||
userdata)
|
||||
return self.conf.notify_add(self.conf_dir + "/stats/enable-disk-poll",
|
||||
cb, userdata)
|
||||
def on_stats_enable_net_poll_changed(self, cb, userdata=None):
|
||||
self.conf.notify_add(self.conf_dir + "/stats/enable-net-poll", cb,
|
||||
userdata)
|
||||
return self.conf.notify_add(self.conf_dir + "/stats/enable-net-poll",
|
||||
cb, userdata)
|
||||
|
||||
# VM Console preferences
|
||||
def on_console_popup_changed(self, callback):
|
||||
|
@ -890,16 +890,34 @@ class vmmConnection(vmmGObject):
|
||||
if self.vmm == None:
|
||||
return
|
||||
|
||||
def cleanup(devs):
|
||||
for dev in devs.values():
|
||||
dev.cleanup()
|
||||
|
||||
self.vmm = None
|
||||
self.nodedevs = {}
|
||||
self.netdevs = {}
|
||||
self.mediadevs = {}
|
||||
self.interfaces = {}
|
||||
self.pools = {}
|
||||
self.nets = {}
|
||||
self.vms = {}
|
||||
self.record = []
|
||||
|
||||
cleanup(self.nodedevs)
|
||||
self.nodedevs = {}
|
||||
|
||||
cleanup(self.netdevs)
|
||||
self.netdevs = {}
|
||||
|
||||
cleanup(self.mediadevs)
|
||||
self.mediadevs = {}
|
||||
|
||||
cleanup(self.interfaces)
|
||||
self.interfaces = {}
|
||||
|
||||
cleanup(self.pools)
|
||||
self.pools = {}
|
||||
|
||||
cleanup(self.nets)
|
||||
self.nets = {}
|
||||
|
||||
cleanup(self.vms)
|
||||
self.vms = {}
|
||||
|
||||
self._change_state(self.STATE_DISCONNECTED)
|
||||
|
||||
def _open_dev_conn(self, uri):
|
||||
|
@ -966,11 +966,6 @@ class vmmDomain(vmmDomainBase):
|
||||
|
||||
self.lastStatus = libvirt.VIR_DOMAIN_SHUTOFF
|
||||
|
||||
self.config.on_stats_enable_net_poll_changed(
|
||||
self.toggle_sample_network_traffic)
|
||||
self.config.on_stats_enable_disk_poll_changed(
|
||||
self.toggle_sample_disk_io)
|
||||
|
||||
self.getvcpus_supported = support.check_domain_support(self._backend,
|
||||
support.SUPPORT_DOMAIN_GETVCPUS)
|
||||
self.managedsave_supported = self.connection.get_dom_managedsave_supported(self._backend)
|
||||
@ -987,13 +982,22 @@ class vmmDomain(vmmDomainBase):
|
||||
# Determine available XML flags (older libvirt versions will error
|
||||
# out if passed SECURE_XML, INACTIVE_XML, etc)
|
||||
(self._inactive_xml_flags,
|
||||
self._active_xml_flags) = self.connection.get_dom_flags(
|
||||
self._backend)
|
||||
self._active_xml_flags) = self.connection.get_dom_flags(self._backend)
|
||||
|
||||
# Hook up our own status listeners
|
||||
self._update_status()
|
||||
self.connect("status-changed", self._update_start_vcpus)
|
||||
self.connect("config-changed", self._reparse_xml)
|
||||
|
||||
# Hook up listeners that need to be cleaned up
|
||||
self.add_gconf_handle(
|
||||
self.config.on_stats_enable_net_poll_changed(
|
||||
self.toggle_sample_network_traffic))
|
||||
self.add_gconf_handle(
|
||||
self.config.on_stats_enable_disk_poll_changed(
|
||||
self.toggle_sample_disk_io))
|
||||
|
||||
self.add_gobject_handle(
|
||||
self.connect("status-changed", self._update_start_vcpus))
|
||||
self.add_gobject_handle(
|
||||
self.connect("config-changed", self._reparse_xml))
|
||||
|
||||
##########################
|
||||
# Internal virDomain API #
|
||||
|
@ -142,8 +142,10 @@ class vmmMediaDevice(vmmGObject):
|
||||
|
||||
self.poll_signal = util.safe_timeout_add(MEDIA_TIMEOUT * 1000,
|
||||
self._poll_for_media)
|
||||
self.add_gobject_timeout(self.poll_signal)
|
||||
|
||||
def disable_poll_for_media(self):
|
||||
self.remove_gobject_timeout(self.poll_signal)
|
||||
self.poll_signal = None
|
||||
|
||||
def _poll_for_media(self):
|
||||
|
Loading…
Reference in New Issue
Block a user