forked from goodboy/tractor
Just set flag for use-after-closed service nursery calls
parent
10f66e5141
commit
1f0cc15675
|
@ -612,6 +612,8 @@ class Actor:
|
||||||
# TODO: once https://github.com/python-trio/trio/issues/467 gets
|
# TODO: once https://github.com/python-trio/trio/issues/467 gets
|
||||||
# worked out we'll likely want to use that!
|
# worked out we'll likely want to use that!
|
||||||
msg = None
|
msg = None
|
||||||
|
nursery_cancelled_before_task: bool = False
|
||||||
|
|
||||||
log.runtime(f"Entering msg loop for {chan} from {chan.uid}")
|
log.runtime(f"Entering msg loop for {chan} from {chan.uid}")
|
||||||
try:
|
try:
|
||||||
with trio.CancelScope(shield=shield) as loop_cs:
|
with trio.CancelScope(shield=shield) as loop_cs:
|
||||||
|
@ -692,10 +694,16 @@ class Actor:
|
||||||
# spin up a task for the requested function
|
# spin up a task for the requested function
|
||||||
log.runtime(f"Spawning task for {func}")
|
log.runtime(f"Spawning task for {func}")
|
||||||
assert self._service_n
|
assert self._service_n
|
||||||
|
try:
|
||||||
cs = await self._service_n.start(
|
cs = await self._service_n.start(
|
||||||
partial(_invoke, self, cid, chan, func, kwargs),
|
partial(_invoke, self, cid, chan, func, kwargs),
|
||||||
name=funcname,
|
name=funcname,
|
||||||
)
|
)
|
||||||
|
except RuntimeError:
|
||||||
|
# avoid reporting a benign race condition
|
||||||
|
# during actor runtime teardown.
|
||||||
|
nursery_cancelled_before_task = True
|
||||||
|
|
||||||
# never allow cancelling cancel requests (results in
|
# never allow cancelling cancel requests (results in
|
||||||
# deadlock and other weird behaviour)
|
# deadlock and other weird behaviour)
|
||||||
if func != self.cancel:
|
if func != self.cancel:
|
||||||
|
@ -741,14 +749,12 @@ class Actor:
|
||||||
log.runtime(f'channel from {chan.uid} closed abruptly:\n{chan}')
|
log.runtime(f'channel from {chan.uid} closed abruptly:\n{chan}')
|
||||||
|
|
||||||
except (Exception, trio.MultiError) as err:
|
except (Exception, trio.MultiError) as err:
|
||||||
if (
|
if nursery_cancelled_before_task:
|
||||||
isinstance(err, RuntimeError) and
|
sn = self._service_n
|
||||||
self._service_n.cancel_scope.cancel_called
|
assert sn and sn.cancel_scope.cancel_called
|
||||||
):
|
|
||||||
log.cancel(
|
log.cancel(
|
||||||
f'Service nursery cancelled before it handled {funcname}'
|
f'Service nursery cancelled before it handled {funcname}'
|
||||||
)
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# ship any "internal" exception (i.e. one from internal
|
# ship any "internal" exception (i.e. one from internal
|
||||||
# machinery not from an rpc task) to parent
|
# machinery not from an rpc task) to parent
|
||||||
|
|
Loading…
Reference in New Issue