forked from goodboy/tractor
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 #115drop_cloudpickle
parent
4de75c3a9d
commit
a215df8dfc
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue