Parcourir la source

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.
Marek Marczykowski-Górecki il y a 6 ans
Parent
commit
12b7e22d27
4 fichiers modifiés avec 12 ajouts et 7 suppressions
  1. 1 1
      qubes/tests/vm/adminvm.py
  2. 8 2
      qubes/vm/__init__.py
  3. 1 1
      qubes/vm/adminvm.py
  4. 2 3
      qubes/vm/qubesvm.py

+ 1 - 1
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'):

+ 8 - 2
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(),

+ 1 - 1
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

+ 2 - 3
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`.'''