forked from goodboy/tractor
1
0
Fork 0
tractor/tests
Tyler Goodlet a870df68c0 Hack `asyncio` to not abandon a guest-mode run?
Took me a while to figure out what the heck was going on but, turns out
`asyncio` changed their SIGINT handling in 3.11 as per:

https://docs.python.org/3/library/asyncio-runner.html#handling-keyboard-interruption

I'm not entirely sure if it's the 3.11 changes or possibly wtv further
updates were made in 3.12  but more or less due to the way
our current main task was written the `trio` guest-run was getting
abandoned on SIGINTs sent from the OS to the infected child proc..

Note that much of the bug and soln cases are layed out in very detailed
comment-notes both in the new test and `run_as_asyncio_guest()`, right
above the final "fix" lines.

Add new `test_infected_aio.test_sigint_closes_lifetime_stack()` test suite
which reliably triggers all abandonment issues with multiple cases
of different parent behaviour post-sending-SIGINT-to-child:
 1. briefly sleep then raise a KBI in the parent which was originally
    demonstrating the file leak not being cleaned up by `Actor.lifetime_stack.close()`
    and simulates a ctl-c from the console (relayed in tandem by
    the OS to the parent and child processes).
 2. do `Context.wait_for_result()` on the child context which would
    hang and timeout since the actor runtime would never complete and
    thus never relay a `ContextCancelled`.
 3. both with and without running a `asyncio` task in the `manage_file`
    child actor; originally it seemed that with an aio task scheduled in
    the child actor the guest-run abandonment always was the "loud" case
    where there seemed to be some actor teardown but with tbs from
    python failing to gracefully exit the `trio` runtime..

The (seemingly working) "fix" required 2 lines of code to be run inside
a `asyncio.CancelledError` handler around the call to `await trio_done_fut`:
- `Actor.cancel_soon()` which schedules the actor runtime to cancel on
  the next `trio` runner cycle and results in a "self cancellation" of
  the actor.
- "pumping the `asyncio` event loop" with a non-0 `.sleep(0.1)` XD
 |_ seems that a "shielded" pump with some actual `delay: float >= 0`
   did the trick to get `asyncio` to allow the `trio` runner/loop to
   fully complete its guest-run without abandonment.

Other supporting changes:
- move `._exceptions.AsyncioCancelled`, our renamed
  `asyncio.CancelledError` error-sub-type-wrapper, to `.to_asyncio` and make
  it derive from `CancelledError` so as to be sure when raised by our
  `asyncio` x-> `trio` exception relay machinery that `asyncio` is
  getting the specific type it expects during cancellation.
- do "summary status" style logging in `run_as_asyncio_guest()` wherein
  we compile the eventual `startup_msg: str` emitted just before waiting
  on the `trio_done_fut`.
- shield-wait with `out: Outcome = await asyncio.shield(trio_done_fut)`
  even though it seems to do nothing in the SIGINT handling case..(I
  presume it might help avoid abandonment in a `asyncio.Task.cancel()`
  case maybe?)
2024-06-24 16:10:23 -04:00
..
conftest.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_2way.py Move context-streaming operational tests into one mod 2021-12-06 16:45:44 -05:00
test_advanced_faults.py Update tests for `PldRx` and `Context` changes 2024-05-09 16:48:53 -04:00
test_advanced_streaming.py Tweak some tests for spurious failues 2024-03-11 10:37:34 -04:00
test_cancellation.py Update tests for `PldRx` and `Context` changes 2024-05-09 16:48:53 -04:00
test_caps_based_msging.py More msg-spec tests tidying 2024-04-14 19:50:09 -04:00
test_child_manages_service_nursery.py Adjust all `RemoteActorError.type` using tests 2024-03-19 18:08:54 -04:00
test_clustering.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_context_stream_semantics.py Add a "current IPC `Context`" `ContextVar` 2024-05-07 15:35:45 -04:00
test_debugger.py Use new `._debug._repl_fail_msg` inside `test_pause_from_sync` 2024-06-10 17:57:43 -04:00
test_discovery.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_docs_examples.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_infected_asyncio.py Hack `asyncio` to not abandon a guest-mode run? 2024-06-24 16:10:23 -04:00
test_inter_peer_cancellation.py Update tests for `PldRx` and `Context` changes 2024-05-09 16:48:53 -04:00
test_legacy_one_way_streaming.py Flip a last `MultiError` to a beg, add todo on `@stream` func 2024-04-14 19:39:57 -04:00
test_local.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_multi_program.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_pldrx_limiting.py Update pld-rx limiting test(s) to use deco input 2024-06-17 09:24:03 -04:00
test_pubsub.py Add (back) a `tractor._testing` sub-pkg 2024-03-13 09:09:08 -04:00
test_resource_cache.py Bump timeout on resource cache test a bitty bit. 2024-01-03 22:27:05 -05:00
test_rpc.py Adjust all `RemoteActorError.type` using tests 2024-03-19 18:08:54 -04:00
test_runtime.py Drop now-deprecated deps on modern `trio`/Python 2024-03-13 18:41:24 -04:00
test_shm.py Pass `str` dtype for `use_str` case 2023-06-15 12:20:20 -04:00
test_spawning.py Update tests for `PldRx` and `Context` changes 2024-05-09 16:48:53 -04:00
test_task_broadcasting.py Port all tests to new `reg_addr` fixture name 2023-10-18 15:39:20 -04:00
test_trioisms.py Drop now-deprecated deps on modern `trio`/Python 2024-03-13 18:41:24 -04:00