From a215df8dfc255897157b29780bfa57214cfff8a1 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 21 Jul 2020 00:23:14 -0400 Subject: [PATCH] Add true ctrl-c tests using an out-of-band SIGINT Verify ctrl-c, as a user would trigger it, properly cancels the actor tree. This was an issue with `trio-run-in-process` that clearly wasn't being handled correctly but for sure is now with the plain old `trio` process spawner. Resolves #115 --- tests/test_cancellation.py | 51 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/tests/test_cancellation.py b/tests/test_cancellation.py index 603fff0..0dbf2fe 100644 --- a/tests/test_cancellation.py +++ b/tests/test_cancellation.py @@ -1,6 +1,8 @@ """ Cancellation and error propagation """ +import os +import signal import platform from itertools import repeat @@ -17,7 +19,7 @@ async def assert_err(delay=0): async def sleep_forever(): - await trio.sleep(float('inf')) + await trio.sleep_forever() async def do_nuthin(): @@ -161,7 +163,7 @@ async def test_cancel_infinite_streamer(start_method): with trio.move_on_after(1) as cancel_scope: async with tractor.open_nursery() as n: portal = await n.start_actor( - f'donny', + 'donny', rpc_module_paths=[__name__], ) @@ -335,3 +337,48 @@ async def test_nested_multierrors(loglevel, start_method): else: assert (subexc.type is tractor.RemoteActorError) or ( subexc.type is trio.Cancelled) + + +def test_open_in_proc_cancel_via_SIGINT(loglevel, start_method): + """Ensure that a control-C (SIGINT) signal cancels both the parent and + child processes in trionic fashion + """ + pid = os.getpid() + + async def main(): + with trio.fail_after(2): + async with tractor.open_nursery() as tn: + await tn.start_actor('sucka') + os.kill(pid, signal.SIGINT) + await trio.sleep_forever() + + with pytest.raises(KeyboardInterrupt): + tractor.run(main) + + +def test_open_in_proc_cancel_via_SIGINT_other_task( + loglevel, + start_method +): + """Ensure that a control-C (SIGINT) signal cancels both the parent + and child processes in trionic fashion even a subprocess is started + from a seperate ``trio`` child task. + """ + pid = os.getpid() + + async def spawn_and_sleep_forever(task_status=trio.TASK_STATUS_IGNORED): + async with tractor.open_nursery() as tn: + for i in range(3): + await tn.run_in_actor('sucka', sleep_forever) + task_status.started() + await trio.sleep_forever() + + async def main(): + # should never timeout since SIGINT should cancel the current program + with trio.fail_after(2): + async with trio.open_nursery() as n: + await n.start(spawn_and_sleep_forever) + os.kill(pid, signal.SIGINT) + + with pytest.raises(KeyboardInterrupt): + tractor.run(main)