qubes/tests: fix some of the fd leaks

This is WIP, there are more fds leaking.
This commit is contained in:
Wojtek Porczyk 2017-08-28 17:10:20 +02:00
parent f1334e5095
commit d0f2fdba55
3 changed files with 54 additions and 44 deletions

View File

@ -605,7 +605,8 @@ class SystemTestCase(QubesTestCase):
if not in_dom0:
self.skipTest('outside dom0')
super(SystemTestCase, self).setUp()
libvirtaio.virEventRegisterAsyncIOImpl(loop=self.loop)
self.libvirt_event_impl = libvirtaio.virEventRegisterAsyncIOImpl(
loop=self.loop)
self.remove_test_vms()
# need some information from the real qubes.xml - at least installed
@ -619,7 +620,7 @@ class SystemTestCase(QubesTestCase):
shutil.copy(self.host_app.store, XMLPATH)
self.app = qubes.Qubes(XMLPATH)
os.environ['QUBES_XML_PATH'] = XMLPATH
self.app.vmm.register_event_handlers(self.app)
self.app.register_event_handlers()
self.qubesd = self.loop.run_until_complete(
qubes.api.create_servers(
@ -627,6 +628,54 @@ class SystemTestCase(QubesTestCase):
qubes.api.internal.QubesInternalAPI,
app=self.app, debug=True))
def tearDown(self):
self.remove_test_vms()
# close the servers before super(), because that might close the loop
server = None
for server in self.qubesd:
for sock in server.sockets:
os.unlink(sock.getsockname())
server.close()
del server
# close all existing connections, especially this will interrupt
# running admin.Events calls, which do keep reference to Qubes() and
# libvirt connection
conn = None
for conn in qubes.api.QubesDaemonProtocol.connections:
if conn.transport:
conn.transport.abort()
del conn
self.loop.run_until_complete(asyncio.wait([
server.wait_closed() for server in self.qubesd]))
del self.qubesd
# remove all references to any complex qubes objects, to release
# resources - most importantly file descriptors; this object will live
# during the whole test run, but all the file descriptors would be
# depleted earlier
self.app.close()
self.host_app.close()
del self.app
del self.host_app
for attr in dir(self):
obj_type = type(getattr(self, attr))
if obj_type.__module__.startswith('qubes'):
delattr(self, attr)
# then trigger garbage collector to really destroy those objects
gc.collect()
self.loop.run_until_complete(self.libvirt_event_impl.drain())
if not self.libvirt_event_impl.is_idle():
self.log.warning(
'libvirt event impl not clean: callbacks %r descriptors %r',
self.libvirt_event_impl.callbacks,
self.libvirt_event_impl.descriptors)
super(SystemTestCase, self).tearDown()
def init_default_template(self, template=None):
if template is None:
template = self.host_app.default_template
@ -675,47 +724,6 @@ class SystemTestCase(QubesTestCase):
self.pool = self.app.add_pool(**POOL_CONF)
self.created_pool = True
def tearDown(self):
self.remove_test_vms()
# close the servers before super(), because that might close the loop
server = None
for server in self.qubesd:
for sock in server.sockets:
os.unlink(sock.getsockname())
server.close()
del server
# close all existing connections, especially this will interrupt
# running admin.Events calls, which do keep reference to Qubes() and
# libvirt connection
conn = None
for conn in qubes.api.QubesDaemonProtocol.connections:
if conn.transport:
conn.transport.abort()
del conn
self.loop.run_until_complete(asyncio.wait([
server.wait_closed() for server in self.qubesd]))
del self.qubesd
# remove all references to any complex qubes objects, to release
# resources - most importantly file descriptors; this object will live
# during the whole test run, but all the file descriptors would be
# depleted earlier
self.app.vmm._libvirt_conn = None
del self.app
del self.host_app
for attr in dir(self):
obj_type = type(getattr(self, attr))
if obj_type.__module__.startswith('qubes'):
delattr(self, attr)
# then trigger garbage collector to really destroy those objects
gc.collect()
super(SystemTestCase, self).tearDown()
def _remove_vm_qubes(self, vm):
vmname = vm.name
app = vm.app

View File

@ -275,7 +275,7 @@ class TC_90_Qubes(qubes.tests.QubesTestCase):
os.unlink('/tmp/qubestest.xml')
except FileNotFoundError:
pass
qubes.Qubes.create_empty_store('/tmp/qubestest.xml')
qubes.Qubes.create_empty_store('/tmp/qubestest.xml').close()
def test_100_clockvm(self):
app = qubes.Qubes('/tmp/qubestest.xml', load=False, offline_mode=True)
@ -295,6 +295,7 @@ class TC_90_Qubes(qubes.tests.QubesTestCase):
self.assertNotIn('service.clocksync', appvm.features)
self.assertIn('service.clocksync', template.features)
self.assertTrue(template.features['service.clocksync'])
app.close()
@qubes.tests.skipUnlessGit
def test_900_example_xml_in_doc(self):

View File

@ -92,6 +92,7 @@ class TC_00_Pool(SystemTestCase):
def setUp(self):
super(TC_00_Pool, self).setUp()
self.app.close()
self.app = TestApp()
def test_000_unknown_pool_driver(self):