17
17
from trio ._core ._traps import RaiseCancelT
18
18
19
19
from ._core import (
20
+ CancelScope ,
20
21
RunVar ,
21
22
TrioToken ,
22
23
disable_ki_protection ,
@@ -86,6 +87,7 @@ class Run(Generic[RetT]):
86
87
queue : stdlib_queue .SimpleQueue [outcome .Outcome [RetT ]] = attr .ib (
87
88
init = False , factory = stdlib_queue .SimpleQueue
88
89
)
90
+ scope : CancelScope = attr .ib (init = False , factory = CancelScope )
89
91
90
92
@disable_ki_protection
91
93
async def unprotected_afn (self ) -> RetT :
@@ -106,7 +108,12 @@ async def run(self) -> None:
106
108
await trio .lowlevel .cancel_shielded_checkpoint ()
107
109
108
110
async def run_system (self ) -> None :
109
- result = await outcome .acapture (self .unprotected_afn )
111
+ # NOTE: There is potential here to only conditionally enter a CancelScope
112
+ # when we need it, sparing some computation. But doing so adds substantial
113
+ # complexity, so we'll leave it until real need is demonstrated.
114
+ with self .scope :
115
+ result = await outcome .acapture (self .unprotected_afn )
116
+ assert not self .scope .cancelled_caught , "any Cancelled should go to our parent"
110
117
self .queue .put_nowait (result )
111
118
112
119
@@ -403,13 +410,14 @@ def _send_message_to_host_task(
403
410
message : Run [RetT ] | RunSync [RetT ], trio_token : TrioToken
404
411
) -> None :
405
412
task_register = PARENT_TASK_DATA .task_register
406
- cancel_register = PARENT_TASK_DATA .cancel_register
407
413
408
414
def in_trio_thread () -> None :
409
415
task = task_register [0 ]
410
416
if task is None :
411
- raise_cancel = cancel_register [0 ]
412
- message .queue .put_nowait (outcome .capture (raise_cancel ))
417
+ # Our parent task is gone! Punt to a system task.
418
+ if isinstance (message , Run ):
419
+ message .scope .cancel ()
420
+ _send_message_to_system_task (message , trio_token )
413
421
else :
414
422
trio .lowlevel .reschedule (task , outcome .Value (message ))
415
423
@@ -509,8 +517,6 @@ def from_thread_run_sync(
509
517
Raises:
510
518
RunFinishedError: if the corresponding call to `trio.run` has
511
519
already completed.
512
- Cancelled: if the corresponding `trio.to_thread.run_sync` task is
513
- cancellable and exits before this function is called.
514
520
RuntimeError: if you try calling this from inside the Trio thread,
515
521
which would otherwise cause a deadlock or if no ``trio_token`` was
516
522
provided, and we can't infer one from context.
0 commit comments