2024-05-30 21:52:24 +00:00
|
|
|
import trio
|
|
|
|
|
import tractor
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def cancellable_pause_loop(
|
|
|
|
|
task_status: trio.TaskStatus[trio.CancelScope] = trio.TASK_STATUS_IGNORED
|
|
|
|
|
):
|
|
|
|
|
with trio.CancelScope() as cs:
|
|
|
|
|
task_status.started(cs)
|
|
|
|
|
for _ in range(3):
|
|
|
|
|
try:
|
|
|
|
|
# ON first entry, there is no level triggered
|
|
|
|
|
# cancellation yet, so this cp does a parent task
|
|
|
|
|
# ctx-switch so that this scope raises for the NEXT
|
|
|
|
|
# checkpoint we hit.
|
|
|
|
|
await trio.lowlevel.checkpoint()
|
|
|
|
|
await tractor.pause()
|
|
|
|
|
|
|
|
|
|
cs.cancel()
|
|
|
|
|
|
|
|
|
|
# parent should have called `cs.cancel()` by now
|
|
|
|
|
await trio.lowlevel.checkpoint()
|
|
|
|
|
|
|
|
|
|
except trio.Cancelled:
|
|
|
|
|
print('INSIDE SHIELDED PAUSE')
|
|
|
|
|
await tractor.pause(shield=True)
|
|
|
|
|
else:
|
|
|
|
|
# should raise it again, bubbling up to parent
|
|
|
|
|
print('BUBBLING trio.Cancelled to parent task-nursery')
|
|
|
|
|
await trio.lowlevel.checkpoint()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def pm_on_cancelled():
|
|
|
|
|
async with trio.open_nursery() as tn:
|
|
|
|
|
tn.cancel_scope.cancel()
|
|
|
|
|
try:
|
|
|
|
|
await trio.sleep_forever()
|
|
|
|
|
except trio.Cancelled:
|
|
|
|
|
# should also raise `Cancelled` since
|
|
|
|
|
# we didn't pass `shield=True`.
|
|
|
|
|
try:
|
|
|
|
|
await tractor.post_mortem(hide_tb=False)
|
|
|
|
|
except trio.Cancelled as taskc:
|
|
|
|
|
|
|
|
|
|
# should enter just fine, in fact it should
|
|
|
|
|
# be debugging the internals of the previous
|
|
|
|
|
# sin-shield call above Bo
|
|
|
|
|
await tractor.post_mortem(
|
|
|
|
|
hide_tb=False,
|
|
|
|
|
shield=True,
|
|
|
|
|
)
|
|
|
|
|
raise taskc
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
raise RuntimeError('Dint cancel as expected!?')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def cancelled_before_pause(
|
|
|
|
|
):
|
|
|
|
|
'''
|
|
|
|
|
Verify that using a shielded pause works despite surrounding
|
|
|
|
|
cancellation called state in the calling task.
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
async with trio.open_nursery() as tn:
|
|
|
|
|
cs: trio.CancelScope = await tn.start(cancellable_pause_loop)
|
|
|
|
|
await trio.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
assert cs.cancelled_caught
|
|
|
|
|
|
|
|
|
|
await pm_on_cancelled()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async def main():
|
|
|
|
|
async with tractor.open_nursery(
|
|
|
|
|
debug_mode=True,
|
|
|
|
|
) as n:
|
|
|
|
|
portal: tractor.Portal = await n.run_in_actor(
|
|
|
|
|
cancelled_before_pause,
|
|
|
|
|
)
|
Fix review nits from PR #460 self-review
Address the actionable findings from the `/code-review` pass
(#1-6); the d2-ext + docstring nits (#7-10) are left for a
follow-up.
Deats,
- `uds_transport_actor_tree.py`: `portal.chan.raddr.sockpath` is
the *shared listener* socket (named for the root registrar), NOT
the child's path — relabel it + lead with the per-child peer pid,
and stop claiming it's the child addr in the docstring,
- `docs.yml`: scope the `pages` `concurrency` group to the `deploy`
job w/ `cancel-in-progress: false` so a PR build can't cancel an
in-flight production deploy,
- `architecture.rst`: `'subint'` is not a selectable `start_method`
on this branch (`SpawnMethodKey` lacks it) — reframe as
in-development/roadmap,
- `context.rst`: `StreamOverrun` isn't re-exported from `tractor`;
point at `tractor._exceptions`,
- `debugging/`: sweep the 3 literalinclude'd examples off the
deprecated `.result()` -> `.wait_for_result()`,
- `quickstart.rst`: proc-title is `name@pid` (per `Aid.reprol`),
not `@uuid`.
NOTE, the `debugging/` examples are pexpect-tested; re-run
`tests/devx/test_debugger.py` for them.
(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2026-06-25 21:07:44 +00:00
|
|
|
await portal.wait_for_result()
|
2024-05-30 21:52:24 +00:00
|
|
|
|
|
|
|
|
# ensure the same works in the root actor!
|
|
|
|
|
await pm_on_cancelled()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
trio.run(main)
|