forked from goodboy/tractor
1
0
Fork 0

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
drop_cloudpickle
Tyler Goodlet 2020-07-21 00:23:14 -04:00
parent 4de75c3a9d
commit a215df8dfc
1 changed files with 49 additions and 2 deletions

View File

@ -1,6 +1,8 @@
""" """
Cancellation and error propagation Cancellation and error propagation
""" """
import os
import signal
import platform import platform
from itertools import repeat from itertools import repeat
@ -17,7 +19,7 @@ async def assert_err(delay=0):
async def sleep_forever(): async def sleep_forever():
await trio.sleep(float('inf')) await trio.sleep_forever()
async def do_nuthin(): 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: with trio.move_on_after(1) as cancel_scope:
async with tractor.open_nursery() as n: async with tractor.open_nursery() as n:
portal = await n.start_actor( portal = await n.start_actor(
f'donny', 'donny',
rpc_module_paths=[__name__], rpc_module_paths=[__name__],
) )
@ -335,3 +337,48 @@ async def test_nested_multierrors(loglevel, start_method):
else: else:
assert (subexc.type is tractor.RemoteActorError) or ( assert (subexc.type is tractor.RemoteActorError) or (
subexc.type is trio.Cancelled) 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)