virtManager: misc reference leak fixes

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2020-09-08 12:27:38 -04:00
parent d073ee9a48
commit 7d69783042
7 changed files with 68 additions and 22 deletions

View File

@ -1068,6 +1068,7 @@ class vmmConnection(vmmGObject):
if not self._objects.add(obj):
log.debug("New %s=%s requested, but it's already tracked.",
class_name, obj.get_name())
obj.cleanup()
return
if not obj.is_nodedev():

View File

@ -1890,8 +1890,11 @@ class vmmCreateVM(vmmGObjectUI):
# We can re-enter this: cleanup() -> close() -> "details-closed"
window = self._customize_window
virtinst_domain = self._customize_window.vm
self._customize_window = None
window.cleanup()
virtinst_domain.cleanup()
virtinst_domain = None
def _show_customize_dialog(self, origguest, installer):
orig_vdomain = vmmDomainVirtinst(self.conn,

View File

@ -532,6 +532,10 @@ class vmmDetails(vmmGObjectUI):
self.vsockdetails = None
self._xmleditor.cleanup()
self._xmleditor = None
self._addstorage.cleanup()
self._addstorage = None
self._os_list.cleanup()
self._os_list = None
##########################

View File

@ -440,6 +440,34 @@ class VNCViewer(Viewer):
# Spice viewer class #
######################
class _SignalTracker:
# Helper class to more conveniently connect and disconnect signals
# from spice objects. This ensures we don't leave circular references
# at object destroy time
def __init__(self):
self._sigmap = {}
def _add_hid(self, obj, hid):
if obj not in self._sigmap:
self._sigmap[obj] = []
self._sigmap[obj].append(hid)
def connect(self, obj, name, handler, *args):
hid = GObject.GObject.connect(obj, name, handler, *args)
self._add_hid(obj, hid)
def connect_after(self, obj, name, handler, *args):
hid = GObject.GObject.connect_after(obj, name, handler, *args)
self._add_hid(obj, hid)
def disconnect_obj_signals(self, obj):
for hid in self._sigmap.get(obj, []):
GObject.GObject.disconnect(obj, hid)
_SIGS = _SignalTracker()
class SpiceViewer(Viewer):
viewer_type = "spice"
@ -449,9 +477,9 @@ class SpiceViewer(Viewer):
self._display = None
self._audio = None
self._main_channel = None
self._main_channel_hids = []
self._display_channel = None
self._usbdev_manager = None
self._channels = set()
###################
@ -472,30 +500,25 @@ class SpiceViewer(Viewer):
else:
self.emit("pointer-ungrab")
def _close_main_channel(self):
for i in self._main_channel_hids:
self._main_channel.handler_disconnect(i)
self._main_channel_hids = []
self._main_channel = None
def _create_spice_session(self):
self._spice_session = SpiceClientGLib.Session()
SpiceClientGLib.set_session_option(self._spice_session)
gtk_session = SpiceClientGtk.GtkSession.get(self._spice_session)
gtk_session.set_property("auto-clipboard", True)
GObject.GObject.connect(self._spice_session, "channel-new",
self._channel_new_cb)
_SIGS.connect(self._spice_session, "channel-new", self._channel_new_cb)
# Distros might have usb redirection compiled out, like OpenBSD
# https://bugzilla.redhat.com/show_bug.cgi?id=1348479
try:
self._usbdev_manager = SpiceClientGLib.UsbDeviceManager.get(
self._spice_session)
self._usbdev_manager.connect("auto-connect-failed",
self._usbdev_redirect_error)
self._usbdev_manager.connect("device-error",
self._usbdev_redirect_error)
_SIGS.connect(
self._usbdev_manager, "auto-connect-failed",
self._usbdev_redirect_error)
_SIGS.connect(
self._usbdev_manager, "device-error",
self._usbdev_redirect_error)
autoredir = self.config.get_auto_usbredir()
if autoredir:
@ -560,18 +583,18 @@ class SpiceViewer(Viewer):
channel.open_fd(fd)
def _channel_new_cb(self, session, channel):
GObject.GObject.connect(channel, "open-fd",
self._channel_open_fd_request)
self._channels.add(channel)
_SIGS.connect(channel, "open-fd", self._channel_open_fd_request)
if (isinstance(channel, SpiceClientGLib.MainChannel) and
not self._main_channel):
self._main_channel = channel
hid = self._main_channel.connect_after("channel-event",
_SIGS.connect_after(
self._main_channel, "channel-event",
self._main_channel_event_cb)
self._main_channel_hids.append(hid)
hid = self._main_channel.connect_after("notify::agent-connected",
_SIGS.connect_after(
self._main_channel, "notify::agent-connected",
self._agent_connected_cb)
self._main_channel_hids.append(hid)
elif (type(channel) == SpiceClientGLib.DisplayChannel and
not self._display):
@ -602,6 +625,7 @@ class SpiceViewer(Viewer):
def close(self):
if self._spice_session is not None:
_SIGS.disconnect_obj_signals(self._spice_session)
self._spice_session.disconnect()
self._spice_session = None
self._audio = None
@ -610,7 +634,13 @@ class SpiceViewer(Viewer):
self._display = None
self._display_channel = None
self._close_main_channel()
for channel in self._channels:
_SIGS.disconnect_obj_signals(channel)
self._channels = None
self._main_channel = None
_SIGS.disconnect_obj_signals(self._usbdev_manager)
self._usbdev_manager = None
def _is_open(self):

View File

@ -60,6 +60,8 @@ class vmmAddStorage(vmmGObjectUI):
def _cleanup(self):
self.conn = None
self.top_box.destroy()
self.advanced_top_box.destroy()
##########################

View File

@ -1659,6 +1659,11 @@ class vmmDomainVirtinst(vmmDomain):
def _get_backend_status(self):
return libvirt.VIR_DOMAIN_SHUTOFF
def _cleanup(self):
self._orig_backend = None
self._installer = None
super()._cleanup()
################
# XML handling #

View File

@ -40,7 +40,7 @@ class vmmXMLEditor(vmmGObjectUI):
self._curpage = _PAGE_DETAILS
self._srcxml = ""
self._srcview = None
self._srcbuf = None
self._srcbuff = None
self._init_ui()
self.details_changed = False
@ -51,7 +51,8 @@ class vmmXMLEditor(vmmGObjectUI):
def _cleanup(self):
pass
self._srcview.destroy()
self._srcbuff = None
###########