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.
This commit is contained in:
Cole Robinson 2012-02-08 14:15:15 -05:00
parent 4ddc0fb486
commit 13dd371e48
2 changed files with 22 additions and 29 deletions

View File

@ -1583,6 +1583,9 @@ class vmmConnection(vmmGObject):
"connection doesn't seem to have dropped. " "connection doesn't seem to have dropped. "
"Ignoring.") "Ignoring.")
for dev in self.mediadevs.values():
dev.tick()
if not noStatsUpdate: if not noStatsUpdate:
self._recalculate_stats(now, updateVMs) self._recalculate_stats(now, updateVMs)

View File

@ -19,6 +19,7 @@
# #
import logging import logging
import time
import virtinst import virtinst
@ -49,7 +50,7 @@ class vmmMediaDevice(vmmGObject):
obj = vmmMediaDevice(path, key, has_media, media_label, media_key, obj = vmmMediaDevice(path, key, has_media, media_label, media_key,
dev, drvtype) dev, drvtype)
obj.enable_poll_for_media() obj.do_poll = True
return obj return obj
@ -65,7 +66,8 @@ class vmmMediaDevice(vmmGObject):
self.media_type = media_type self.media_type = media_type
self.nodedev_obj = nodedev_obj self.nodedev_obj = nodedev_obj
self.poll_signal = None self.do_poll = False
self.last_tick = 0
def _cleanup(self): def _cleanup(self):
pass pass
@ -130,50 +132,38 @@ class vmmMediaDevice(vmmGObject):
######################################### #########################################
# Nodedev API polling for media updates # # Nodedev API polling for media updates #
######################################### #########################################
def enable_poll_for_media(self):
if self.poll_signal: def tick(self):
if not self.nodedev_obj:
return 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
if not self.nodedev_obj:
return False
if not self.nodedev_obj.conn.is_active(): 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: try:
self.nodedev_obj.refresh_xml() self.nodedev_obj.refresh_xml()
xml = self.nodedev_obj.get_xml() xml = self.nodedev_obj.get_xml()
except: except:
# Assume the device was removed # Assume the device was removed
return False return
try: try:
vobj = virtinst.NodeDeviceParser.parse(xml) vobj = virtinst.NodeDeviceParser.parse(xml)
has_media = vobj.media_available has_media = vobj.media_available
except: except:
logging.exception("Node device CDROM polling failed") logging.exception("Node device CDROM polling failed")
return False return
if has_media != self.has_media(): if has_media == self.has_media():
self.set_media(has_media, None, None) return
if has_media:
self.emit("media-added") self.set_media(has_media, None, None)
else: self.idle_emit(has_media and "media-added" or "media-removed")
self.emit("media-removed")
return True
vmmGObject.type_register(vmmMediaDevice) vmmGObject.type_register(vmmMediaDevice)
vmmMediaDevice.signal_new(vmmMediaDevice, "media-added", []) vmmMediaDevice.signal_new(vmmMediaDevice, "media-added", [])