diff --git a/tractor/_root.py b/tractor/_root.py index 9b58523d..3c20fff0 100644 --- a/tractor/_root.py +++ b/tractor/_root.py @@ -69,6 +69,20 @@ from ._exceptions import ( logger = log.get_logger('tractor') +# Spawn backends under which `debug_mode=True` is supported. +# Requirement: the spawned subactor's root runtime must be +# trio-native so `tractor.devx.debug._tty_lock` works. Matches +# both the enable-site in `open_root_actor` and the cleanup- +# site reset of `_runtime_vars['_debug_mode']` — keep them in +# lockstep when adding backends. +_DEBUG_COMPATIBLE_BACKENDS: tuple[str, ...] = ( + 'trio', + # forkserver children run `_trio_main` in their own OS + # process — same child-side runtime shape as `trio_proc`. + 'subint_forkserver', +) + + # TODO: stick this in a `@acm` defined in `devx.debug`? # -[ ] also maybe consider making this a `wrapt`-deco to # save an indent level? @@ -293,10 +307,14 @@ async def open_root_actor( ) loglevel: str = loglevel.upper() + # Debug-mode is currently only supported for backends whose + # subactor root runtime is trio-native (so `tractor.devx. + # debug._tty_lock` works). See `_DEBUG_COMPATIBLE_BACKENDS` + # module-const for the list. if ( debug_mode and - _spawn._spawn_method == 'trio' + _spawn._spawn_method in _DEBUG_COMPATIBLE_BACKENDS ): _state._runtime_vars['_debug_mode'] = True @@ -318,7 +336,9 @@ async def open_root_actor( elif debug_mode: raise RuntimeError( - "Debug mode is only supported for the `trio` backend!" + f'Debug mode currently supported only for ' + f'{_DEBUG_COMPATIBLE_BACKENDS!r} spawn backends, not ' + f'{_spawn._spawn_method!r}.' ) assert loglevel @@ -619,7 +639,7 @@ async def open_root_actor( if ( debug_mode and - _spawn._spawn_method == 'trio' + _spawn._spawn_method in _DEBUG_COMPATIBLE_BACKENDS ): _state._runtime_vars['_debug_mode'] = False diff --git a/tractor/runtime/_runtime.py b/tractor/runtime/_runtime.py index 0c25b926..cbfaa313 100644 --- a/tractor/runtime/_runtime.py +++ b/tractor/runtime/_runtime.py @@ -870,7 +870,14 @@ class Actor: accept_addrs: list[UnwrappedAddress]|None = None - if self._spawn_method in ("trio", "subint"): + if self._spawn_method in ( + 'trio', + 'subint', + # `subint_forkserver` parent-side sends a + # `SpawnSpec` over IPC just like the other two + # — fork child-side runtime is trio-native. + 'subint_forkserver', + ): # Receive post-spawn runtime state from our parent. spawnspec: msgtypes.SpawnSpec = await chan.recv()