mtest: add back SIGINT handling

pull/7836/head
Paolo Bonzini 4 years ago
parent 659a5cbaa3
commit 8cf90e6370
  1. 33
      mesonbuild/mtest.py

@ -608,6 +608,13 @@ def load_tests(build_dir: str) -> T.List[TestSerialisation]:
# Custom waiting primitives for asyncio # Custom waiting primitives for asyncio
async def complete(future: asyncio.Future) -> None:
"""Wait for completion of the given future, ignoring cancellation."""
try:
await future
except asyncio.CancelledError:
pass
async def complete_all(futures: T.Iterable[asyncio.Future]) -> None: async def complete_all(futures: T.Iterable[asyncio.Future]) -> None:
"""Wait for completion of all the given futures, ignoring cancellation.""" """Wait for completion of all the given futures, ignoring cancellation."""
while futures: while futures:
@ -1161,10 +1168,11 @@ class TestHarness:
if self.options.wd: if self.options.wd:
os.chdir(self.options.wd) os.chdir(self.options.wd)
self.build_data = build.load(os.getcwd()) self.build_data = build.load(os.getcwd())
interrupted = False
async def run_test(test: SingleTestRunner, async def run_test(test: SingleTestRunner,
name: str, index: int) -> None: name: str, index: int) -> None:
if self.options.repeat > 1 and self.fail_count: if interrupted or (self.options.repeat > 1 and self.fail_count):
return return
res = await asyncio.get_event_loop().run_in_executor(executor, test.run) res = await asyncio.get_event_loop().run_in_executor(executor, test.run)
self.process_test_result(res) self.process_test_result(res)
@ -1175,6 +1183,17 @@ class TestHarness:
f.result() f.result()
futures.remove(f) futures.remove(f)
def cancel_all_futures() -> None:
nonlocal interrupted
if interrupted:
return
interrupted = True
mlog.warning('CTRL-C detected, interrupting')
for f in futures:
f.cancel()
if sys.platform != 'win32':
asyncio.get_event_loop().add_signal_handler(signal.SIGINT, cancel_all_futures)
try: try:
for _ in range(self.options.repeat): for _ in range(self.options.repeat):
for i, test in enumerate(tests, 1): for i, test in enumerate(tests, 1):
@ -1183,11 +1202,11 @@ class TestHarness:
if not test.is_parallel or single_test.options.gdb: if not test.is_parallel or single_test.options.gdb:
await complete_all(futures) await complete_all(futures)
await run_test(single_test, visible_name, i) future = asyncio.ensure_future(run_test(single_test, visible_name, i))
else: futures.append(future)
future = asyncio.ensure_future(run_test(single_test, visible_name, i)) future.add_done_callback(test_done)
futures.append(future) if not test.is_parallel or single_test.options.gdb:
future.add_done_callback(test_done) await complete(future)
if self.options.repeat > 1 and self.fail_count: if self.options.repeat > 1 and self.fail_count:
break break
@ -1198,6 +1217,8 @@ class TestHarness:
if self.logfilename: if self.logfilename:
print('Full log written to {}'.format(self.logfilename)) print('Full log written to {}'.format(self.logfilename))
finally: finally:
if sys.platform != 'win32':
asyncio.get_event_loop().remove_signal_handler(signal.SIGINT)
os.chdir(startdir) os.chdir(startdir)
def list_tests(th: TestHarness) -> bool: def list_tests(th: TestHarness) -> bool:

Loading…
Cancel
Save