utils/QubesWatch: use timers to retry QubesDB watch registration
QubesWatch._register_watches is called from libvirt event callback, asynchronously to qvm-start. This means that `qubesdb-daemon` may not be running or populated yet. If first QubesDB connection (or watch registration) fails, schedule next try using timers in libvirt event API (as it is base of QubesWatch mainloop), instead of some sleep loop. This way other events will be processed in the meantime. QubesOS/qubes-issues#1110
This commit is contained in:
parent
4a4d16feb9
commit
5f0d564051
@ -790,29 +790,41 @@ class QubesWatch(object):
|
||||
name = libvirt_domain.name()
|
||||
if name in self._qdb:
|
||||
return
|
||||
if not libvirt_domain.isActive():
|
||||
return
|
||||
# open separate connection to Qubes DB:
|
||||
# 1. to not confuse pull() with responses to real commands sent from
|
||||
# other threads (like read, write etc) with watch events
|
||||
# 2. to not think whether QubesDB is thread-safe (it isn't)
|
||||
while libvirt_domain.isActive() and name not in self._qdb:
|
||||
try:
|
||||
self._qdb[name] = QubesDB(name)
|
||||
except Error as e:
|
||||
if e.args[0] != 2:
|
||||
raise
|
||||
time.sleep(0.5)
|
||||
if name not in self._qdb:
|
||||
# domain no longer active
|
||||
try:
|
||||
self._qdb[name] = QubesDB(name)
|
||||
except Error as e:
|
||||
if e.args[0] != 2:
|
||||
raise
|
||||
libvirt.virEventAddTimeout(500, self._retry_register_watches,
|
||||
libvirt_domain)
|
||||
return
|
||||
else:
|
||||
name = "dom0"
|
||||
self._qdb[name] = QubesDB(name)
|
||||
self._qdb[name].watch('/qubes-block-devices')
|
||||
try:
|
||||
self._qdb[name].watch('/qubes-block-devices')
|
||||
except Error as e:
|
||||
if e.args[0] == 102: # Connection reset by peer
|
||||
# QubesDB daemon not running - most likely we've connected to
|
||||
# stale daemon which just exited; retry later
|
||||
libvirt.virEventAddTimeout(500, self._retry_register_watches,
|
||||
libvirt_domain)
|
||||
return
|
||||
self._qdb_events[name] = libvirt.virEventAddHandle(
|
||||
self._qdb[name].watch_fd(),
|
||||
libvirt.VIR_EVENT_HANDLE_READABLE,
|
||||
self._qdb_handler, name)
|
||||
|
||||
def _retry_register_watches(self, timer, libvirt_domain):
|
||||
libvirt.virRemoveTimeout(timer)
|
||||
self._register_watches(libvirt_domain)
|
||||
|
||||
def _unregister_watches(self, libvirt_domain):
|
||||
name = libvirt_domain.name()
|
||||
if name in self._qdb_events:
|
||||
|
Loading…
Reference in New Issue
Block a user