Kaynağa Gözat

Merge branch 'tests-leaks'

* tests-leaks:
  ext/pci: handle 'qubes-close' event
  tests: allow extensions to cleanup objects references
Marek Marczykowski-Górecki 4 yıl önce
ebeveyn
işleme
e6aa35fcdf
4 değiştirilmiş dosya ile 26 ekleme ve 1 silme
  1. 17 0
      qubes/app.py
  2. 6 0
      qubes/ext/pci.py
  3. 0 1
      qubes/tests/__init__.py
  4. 3 0
      qubes/tests/vm/qubesvm.py

+ 17 - 0
qubes/app.py

@@ -724,6 +724,17 @@ class Qubes(qubes.PropertyHolder):
             :param event: Event name (``'pool-delete'``)
             :param pool: Pool object
 
+        .. event:: qubes-close (subject, event)
+
+            Fired when this Qubes() object instance is going to be closed
+            and destroyed. In practice it is called only during tests, to
+            cleanup objects from one test, before another.
+            It is _not_ called when qubesd daemon is stopped.
+
+            :param subject: Event emitter
+            :param event: Event name (``'qubes-close'``)
+
+
     Methods and attributes:
     """
     default_guivm = qubes.VMProperty(
@@ -1085,6 +1096,9 @@ class Qubes(qubes.PropertyHolder):
         for frame in traceback.extract_stack():
             self.log.debug('%s', frame)
 
+        # let all the extension cleanup things
+        self.fire_event('qubes-close')
+
         super().close()
 
         if self._domain_event_callback_id is not None:
@@ -1094,6 +1108,9 @@ class Qubes(qubes.PropertyHolder):
 
         # Only our Lord, The God Almighty, knows what references
         # are kept in extensions.
+        # NOTE: this doesn't really delete extension objects - Extension class
+        # saves reference to instance, and also various registered (class level)
+        # event handlers do that too
         del self._extensions
 
         for vm in self.domains:

+ 6 - 0
qubes/ext/pci.py

@@ -313,6 +313,12 @@ class PCIDeviceExtension(qubes.ext.Extension):
             else:
                 raise
 
+    @qubes.ext.handler('qubes-close', system=True)
+    def on_app_close(self, app, event):
+        # pylint: disable=unused-argument,no-self-use
+        _cache_get.cache_clear()
+
+
 @functools.lru_cache(maxsize=None)
 def _cache_get(vm, ident):
     ''' Caching wrapper around `PCIDevice(vm, ident)`. '''

+ 0 - 1
qubes/tests/__init__.py

@@ -410,7 +410,6 @@ class QubesTestCase(unittest.TestCase):
         self.loop = asyncio.get_event_loop()
         self.addCleanup(self.cleanup_loop)
         self.addCleanup(self.cleanup_traceback)
-        self.addCleanup(qubes.ext.pci._cache_get.cache_clear)
 
     def cleanup_traceback(self):
         '''Remove local variables reference from tracebacks to allow garbage

+ 3 - 0
qubes/tests/vm/qubesvm.py

@@ -273,6 +273,9 @@ class QubesVMTestsMixin(object):
 
     def tearDown(self):
         try:
+            # self.app is not a real events emiter, so make the call manually
+            for handler in qubes.Qubes.__handlers__.get('qubes-close'):
+                handler(self.app, 'qubes-close')
             self.app.domains.close()
         except AttributeError:
             pass