Port to new debug api, set `_is_root` state flag on startup
parent
150179bfe4
commit
8b6e9f5530
|
@ -7,7 +7,6 @@ from itertools import chain
|
||||||
import importlib
|
import importlib
|
||||||
import importlib.util
|
import importlib.util
|
||||||
import inspect
|
import inspect
|
||||||
import bdb
|
|
||||||
import uuid
|
import uuid
|
||||||
import typing
|
import typing
|
||||||
from typing import Dict, List, Tuple, Any, Optional
|
from typing import Dict, List, Tuple, Any, Optional
|
||||||
|
@ -27,6 +26,7 @@ from ._exceptions import (
|
||||||
unpack_error,
|
unpack_error,
|
||||||
ModuleNotExposed
|
ModuleNotExposed
|
||||||
)
|
)
|
||||||
|
from ._debug import _maybe_enter_pm
|
||||||
from ._discovery import get_arbiter
|
from ._discovery import get_arbiter
|
||||||
from ._portal import Portal
|
from ._portal import Portal
|
||||||
from . import _state
|
from . import _state
|
||||||
|
@ -127,13 +127,8 @@ async def _invoke(
|
||||||
await chan.send({'return': await coro, 'cid': cid})
|
await chan.send({'return': await coro, 'cid': cid})
|
||||||
except (Exception, trio.MultiError) as err:
|
except (Exception, trio.MultiError) as err:
|
||||||
# NOTE: don't enter debug mode recursively after quitting pdb
|
# NOTE: don't enter debug mode recursively after quitting pdb
|
||||||
if _state.debug_mode() and not isinstance(err, bdb.BdbQuit):
|
|
||||||
# Allow for pdb control in parent
|
|
||||||
from ._debug import post_mortem
|
|
||||||
log.exception("Actor crashed, entering debug mode:")
|
|
||||||
await post_mortem()
|
|
||||||
else:
|
|
||||||
log.exception("Actor crashed:")
|
log.exception("Actor crashed:")
|
||||||
|
await _maybe_enter_pm(err)
|
||||||
|
|
||||||
# always ship errors back to caller
|
# always ship errors back to caller
|
||||||
err_msg = pack_error(err)
|
err_msg = pack_error(err)
|
||||||
|
@ -201,6 +196,7 @@ class Actor:
|
||||||
"""
|
"""
|
||||||
self.name = name
|
self.name = name
|
||||||
self.uid = (name, uid or str(uuid.uuid4()))
|
self.uid = (name, uid or str(uuid.uuid4()))
|
||||||
|
self._is_cancelled: bool = False
|
||||||
|
|
||||||
# retreive and store parent `__main__` data which
|
# retreive and store parent `__main__` data which
|
||||||
# will be passed to children
|
# will be passed to children
|
||||||
|
@ -251,7 +247,7 @@ class Actor:
|
||||||
self._parent_chan: Optional[Channel] = None
|
self._parent_chan: Optional[Channel] = None
|
||||||
self._forkserver_info: Optional[
|
self._forkserver_info: Optional[
|
||||||
Tuple[Any, Any, Any, Any, Any]] = None
|
Tuple[Any, Any, Any, Any, Any]] = None
|
||||||
self._actoruid2nursery: Dict[str, 'ActorNursery'] = {}
|
self._actoruid2nursery: Dict[str, 'ActorNursery'] = {} # noqa
|
||||||
|
|
||||||
async def wait_for_peer(
|
async def wait_for_peer(
|
||||||
self, uid: Tuple[str, str]
|
self, uid: Tuple[str, str]
|
||||||
|
@ -564,7 +560,7 @@ class Actor:
|
||||||
f"Exiting msg loop for {chan} from {chan.uid} "
|
f"Exiting msg loop for {chan} from {chan.uid} "
|
||||||
f"with last msg:\n{msg}")
|
f"with last msg:\n{msg}")
|
||||||
|
|
||||||
async def _chan_to_parent(
|
async def _from_parent(
|
||||||
self,
|
self,
|
||||||
parent_addr: Optional[Tuple[str, int]],
|
parent_addr: Optional[Tuple[str, int]],
|
||||||
) -> Tuple[Channel, Optional[Tuple[str, int]]]:
|
) -> Tuple[Channel, Optional[Tuple[str, int]]]:
|
||||||
|
@ -593,6 +589,10 @@ class Actor:
|
||||||
parent_data.pop('bind_host'),
|
parent_data.pop('bind_host'),
|
||||||
parent_data.pop('bind_port'),
|
parent_data.pop('bind_port'),
|
||||||
)
|
)
|
||||||
|
rvs = parent_data.pop('_runtime_vars')
|
||||||
|
rvs['_is_root'] = False
|
||||||
|
_state._runtime_vars.update(rvs)
|
||||||
|
|
||||||
for attr, value in parent_data.items():
|
for attr, value in parent_data.items():
|
||||||
setattr(self, attr, value)
|
setattr(self, attr, value)
|
||||||
|
|
||||||
|
@ -630,13 +630,13 @@ class Actor:
|
||||||
# establish primary connection with immediate parent
|
# establish primary connection with immediate parent
|
||||||
self._parent_chan = None
|
self._parent_chan = None
|
||||||
if parent_addr is not None:
|
if parent_addr is not None:
|
||||||
self._parent_chan, accept_addr_from_rent = await self._chan_to_parent(
|
self._parent_chan, accept_addr_rent = await self._from_parent(
|
||||||
parent_addr)
|
parent_addr)
|
||||||
|
|
||||||
# either it's passed in because we're not a child
|
# either it's passed in because we're not a child
|
||||||
# or because we're running in mp mode
|
# or because we're running in mp mode
|
||||||
if accept_addr_from_rent is not None:
|
if accept_addr_rent is not None:
|
||||||
accept_addr = accept_addr_from_rent
|
accept_addr = accept_addr_rent
|
||||||
|
|
||||||
# load exposed/allowed RPC modules
|
# load exposed/allowed RPC modules
|
||||||
# XXX: do this **after** establishing a channel to the parent
|
# XXX: do this **after** establishing a channel to the parent
|
||||||
|
@ -711,7 +711,7 @@ class Actor:
|
||||||
|
|
||||||
# Blocks here as expected until the root nursery is
|
# Blocks here as expected until the root nursery is
|
||||||
# killed (i.e. this actor is cancelled or signalled by the parent)
|
# killed (i.e. this actor is cancelled or signalled by the parent)
|
||||||
except (trio.MultiError, Exception) as err:
|
except Exception as err:
|
||||||
if not registered_with_arbiter:
|
if not registered_with_arbiter:
|
||||||
# TODO: I guess we could try to connect back
|
# TODO: I guess we could try to connect back
|
||||||
# to the parent through a channel and engage a debugger
|
# to the parent through a channel and engage a debugger
|
||||||
|
@ -822,6 +822,8 @@ class Actor:
|
||||||
spawning new rpc tasks
|
spawning new rpc tasks
|
||||||
- return control the parent channel message loop
|
- return control the parent channel message loop
|
||||||
"""
|
"""
|
||||||
|
self._is_cancelled = True
|
||||||
|
|
||||||
# cancel all ongoing rpc tasks
|
# cancel all ongoing rpc tasks
|
||||||
with trio.CancelScope(shield=True):
|
with trio.CancelScope(shield=True):
|
||||||
# kill all ongoing tasks
|
# kill all ongoing tasks
|
||||||
|
@ -1039,7 +1041,12 @@ async def _start_actor(
|
||||||
parent_addr=None
|
parent_addr=None
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
try:
|
||||||
result = await main()
|
result = await main()
|
||||||
|
except (Exception, trio.MultiError) as err:
|
||||||
|
log.exception("Actor crashed:")
|
||||||
|
await _maybe_enter_pm(err)
|
||||||
|
raise
|
||||||
|
|
||||||
# XXX: the actor is cancelled when this context is complete
|
# XXX: the actor is cancelled when this context is complete
|
||||||
# given that there are no more active peer channels connected
|
# given that there are no more active peer channels connected
|
||||||
|
|
Loading…
Reference in New Issue