From 12b7e22d2754fcc3c5c1c8f1ce11e4c55ca60cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Thu, 28 Sep 2017 16:12:05 +0200 Subject: [PATCH] vm: do not start QubesDB watch instance multiple times vm.create_qdb_entries can be called multiple times - for example when changing VM IP. Move starting qdb watcher to start(). And just in case, cleanup old watcher (if still exists) before starting new one. This fixes one FD leak. --- qubes/tests/vm/adminvm.py | 2 +- qubes/vm/__init__.py | 10 ++++++++-- qubes/vm/adminvm.py | 2 +- qubes/vm/qubesvm.py | 5 ++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/qubes/tests/vm/adminvm.py b/qubes/tests/vm/adminvm.py index 0560e130..6b70ac48 100644 --- a/qubes/tests/vm/adminvm.py +++ b/qubes/tests/vm/adminvm.py @@ -38,7 +38,7 @@ class TC_00_AdminVM(qubes.tests.QubesTestCase): qubes.vm.adminvm.AdminVM, 'start_qdb_watch') as mock_qdb: self.vm = qubes.vm.adminvm.AdminVM(self.app, xml=None) - mock_qdb.assert_called_once_with('dom0') + mock_qdb.assert_called_once_with() self.addCleanup(self.cleanup_adminvm) except: # pylint: disable=bare-except if self.id().endswith('.test_000_init'): diff --git a/qubes/vm/__init__.py b/qubes/vm/__init__.py index 069d6f2b..2c534773 100644 --- a/qubes/vm/__init__.py +++ b/qubes/vm/__init__.py @@ -486,14 +486,20 @@ class BaseVM(qubes.PropertyHolder): self._qdb_connection_watch.close() self._qdb_connection_watch = None - def start_qdb_watch(self, name, loop=None): + def start_qdb_watch(self, loop=None): '''Start watching QubesDB Calling this method in appropriate time is responsibility of child class. ''' + # cleanup old watch connection first, if any + if self._qdb_connection_watch is not None: + asyncio.get_event_loop().remove_reader( + self._qdb_connection_watch.watch_fd()) + self._qdb_connection_watch.close() + import qubesdb # pylint: disable=import-error - self._qdb_connection_watch = qubesdb.QubesDB(name) + self._qdb_connection_watch = qubesdb.QubesDB(self.name) if loop is None: loop = asyncio.get_event_loop() loop.add_reader(self._qdb_connection_watch.watch_fd(), diff --git a/qubes/vm/adminvm.py b/qubes/vm/adminvm.py index dbee80c3..40566c9d 100644 --- a/qubes/vm/adminvm.py +++ b/qubes/vm/adminvm.py @@ -58,7 +58,7 @@ class AdminVM(qubes.vm.BaseVM): self._libvirt_domain = None if not self.app.vmm.offline_mode: - self.start_qdb_watch('dom0') + self.start_qdb_watch() def __str__(self): return self.name diff --git a/qubes/vm/qubesvm.py b/qubes/vm/qubesvm.py index c187c65d..c2c660e0 100644 --- a/qubes/vm/qubesvm.py +++ b/qubes/vm/qubesvm.py @@ -712,7 +712,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.storage = qubes.storage.Storage(self) if not self.app.vmm.offline_mode and self.is_running(): - self.start_qdb_watch(self.name) + self.start_qdb_watch() @qubes.events.handler('property-set:label') def on_property_set_label(self, event, name, newvalue, oldvalue=None): @@ -847,6 +847,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.log.info('Setting Qubes DB info for the VM') yield from self.start_qubesdb() self.create_qdb_entries() + self.start_qdb_watch() self.log.warning('Activating the {} VM'.format(self.name)) self.libvirt_domain.resume() @@ -1742,8 +1743,6 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM): self.fire_event('domain-qdb-create') - self.start_qdb_watch(self.name) - # TODO async; update this in constructor def _update_libvirt_domain(self): '''Re-initialise :py:attr:`libvirt_domain`.'''