Infinite loop in `TestBase` if event loop is stopped with non-daemon thread
qstokkink opened this issue · 0 comments
qstokkink commented
The following test case spawns a Thread
and stops the event loop. The unit test test_crash_evl
is expected to be terminated after 1 second (MAX_TEST_TIME
). However, the following code never terminates:
from asyncio import get_event_loop
from threading import Thread
from .base import TestBase
class TestCrash(TestBase):
MAX_TEST_TIME = 1.0
def inf_loop(self):
while True:
pass
def setUp(self):
super().setUp()
self.thread = Thread(target=self.inf_loop)
self.thread.start()
def tearDown(self):
super().tearDown()
self.thread.join()
def test_crash_evl(self):
get_event_loop().stop()
The log output for this case is as follows:
The test-suite locked up! Force quitting! Thread dump:
THREAD#139684644501248
| File "/usr/lib/python3.8/threading.py", line 890, in _bootstrap
| self._bootstrap_inner()
| File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
| self.run()
| File "/usr/lib/python3.8/threading.py", line 870, in run
| self._target(*self._args, **self._kwargs)
| File "/py-ipv8/ipv8/test/test_crash.py", line 13, in inf_loop
| pass
THREAD#139684679137088
| File "/snap/pycharm-community/336/plugins/python-ce/helpers/pycharm/_jb_nosetest_runner.py", line 19, in <module>
| sys.exit(nose.main(addplugins=[TeamcityReport()]))
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/core.py", line 118, in __init__
| unittest.TestProgram.__init__(
| File "/usr/lib/python3.8/unittest/main.py", line 101, in __init__
| self.runTests()
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/core.py", line 207, in runTests
| result = self.testRunner.run(self.test)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/core.py", line 62, in run
| test(result)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/suite.py", line 178, in __call__
| return self.run(*arg, **kw)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/suite.py", line 225, in run
| test(orig)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/suite.py", line 178, in __call__
| return self.run(*arg, **kw)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/suite.py", line 225, in run
| test(orig)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/case.py", line 46, in __call__
| return self.run(*arg, **kwarg)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/case.py", line 134, in run
| self.runTest(result)
| File "/home/quinten/.local/lib/python3.8/site-packages/nose/case.py", line 152, in runTest
| test(result)
| File "/usr/lib/python3.8/unittest/case.py", line 736, in __call__
| return self.run(*args, **kwds)
| File "/usr/lib/python3.8/unittest/async_case.py", line 158, in run
| return super().run(result)
| File "/usr/lib/python3.8/unittest/case.py", line 679, in run
| self._callTearDown()
| File "/py-ipv8/ipv8/test/base.py", line 174, in _callTearDown
| self.__call_internal_in_context(self.tearDown)
| File "/py-ipv8/ipv8/test/base.py", line 161, in __call_internal_in_context
| self._callTestMethod(func)
| File "/usr/lib/python3.8/unittest/async_case.py", line 65, in _callTestMethod
| self._callMaybeAsync(method)
| File "/usr/lib/python3.8/unittest/async_case.py", line 84, in _callMaybeAsync
| ret = func(*args, **kwargs)
| File "/py-ipv8/ipv8/test/test_crash.py", line 22, in tearDown
| self.thread.join()
| File "/usr/lib/python3.8/threading.py", line 1011, in join
| self._wait_for_tstate_lock()
| File "/usr/lib/python3.8/threading.py", line 1027, in _wait_for_tstate_lock
| elif lock.acquire(block, timeout):
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
self.run()
File "/usr/lib/python3.8/threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "/py-ipv8/ipv8/test/base.py", line 272, in check_loop
tasks = all_tasks(get_event_loop())
File "/usr/lib/python3.8/asyncio/events.py", line 639, in get_event_loop
raise RuntimeError('There is no current event loop in thread %r.'
RuntimeError: There is no current event loop in thread 'Thread-1'.
In this case, the call to get_event_loop()
crashes in the lock-up detection of TestBase
:
Lines 272 to 276 in 8d2d09c
To fix this issue, this code should handle the case of an event loop being stopped or closed (and perhaps - in exotic situations - not existing at all).