commit 13dd371e4840b8dca70508477cfc6820ac5d9a71 Author: Cole Robinson Date: Wed Feb 8 14:15:15 2012 -0500 Don't let media polling block app if a connection goes down If we unplug a remote machine we are connected to, doing the media timeout with a gobject timeout means running it in the main thread, which if it's blocking on the remote connection will freeze the whole app. diff --git a/src/virtManager/connection.py b/src/virtManager/connection.py index 15c1d5e..d649c44 100644 --- a/src/virtManager/connection.py +++ b/src/virtManager/connection.py @@ -1583,6 +1583,9 @@ class vmmConnection(vmmGObject): "connection doesn't seem to have dropped. " "Ignoring.") + for dev in self.mediadevs.values(): + dev.tick() + if not noStatsUpdate: self._recalculate_stats(now, updateVMs) diff --git a/src/virtManager/mediadev.py b/src/virtManager/mediadev.py index 3731599..a046d9e 100644 --- a/src/virtManager/mediadev.py +++ b/src/virtManager/mediadev.py @@ -19,6 +19,7 @@ # import logging +import time import virtinst @@ -49,7 +50,7 @@ class vmmMediaDevice(vmmGObject): obj = vmmMediaDevice(path, key, has_media, media_label, media_key, dev, drvtype) - obj.enable_poll_for_media() + obj.do_poll = True return obj @@ -65,7 +66,8 @@ class vmmMediaDevice(vmmGObject): self.media_type = media_type self.nodedev_obj = nodedev_obj - self.poll_signal = None + self.do_poll = False + self.last_tick = 0 def _cleanup(self): pass @@ -130,50 +132,38 @@ class vmmMediaDevice(vmmGObject): ######################################### # Nodedev API polling for media updates # ######################################### - def enable_poll_for_media(self): - if self.poll_signal: - return - - self.poll_signal = self.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): - if not self.poll_signal: - return False + def tick(self): if not self.nodedev_obj: - return False + return if not self.nodedev_obj.conn.is_active(): - return False + return + + if (time.time() - self.last_tick) < MEDIA_TIMEOUT: + return + self.last_tick = time.time() try: self.nodedev_obj.refresh_xml() xml = self.nodedev_obj.get_xml() except: # Assume the device was removed - return False + return try: vobj = virtinst.NodeDeviceParser.parse(xml) has_media = vobj.media_available except: logging.exception("Node device CDROM polling failed") - return False + return + + if has_media == self.has_media(): + return - if has_media != self.has_media(): - self.set_media(has_media, None, None) - if has_media: - self.emit("media-added") - else: - self.emit("media-removed") + self.set_media(has_media, None, None) + self.idle_emit(has_media and "media-added" or "media-removed") - return True vmmGObject.type_register(vmmMediaDevice) vmmMediaDevice.signal_new(vmmMediaDevice, "media-added", [])