From 72d1b9016a52f7d2a5e15b1a739e2d9d73c0c400 Mon Sep 17 00:00:00 2001 From: goodboy Date: Thu, 23 Apr 2026 11:39:42 -0400 Subject: [PATCH] Enable `debug_mode` for `subint_forkserver` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `subint_forkserver` backend's child runtime is trio-native (uses `_trio_main` + receives `SpawnSpec` over IPC just like `trio`/`subint`), so `tractor.devx.debug._tty_lock` works in those subactors. Wire the runtime gates that historically hard-coded `_spawn_method == 'trio'` to recognize this third backend. Deats, - new `_DEBUG_COMPATIBLE_BACKENDS` module-const in `tractor._root` listing the spawn backends whose subactor runtime is trio-native (`'trio'`, `'subint_forkserver'`). Both the enable-site (`_runtime_vars['_debug_mode'] = True`) and the cleanup-site reset key. off the same tuple — keep them in lockstep when adding backends - `open_root_actor`'s `RuntimeError` for unsupported backends now reports the full compatible-set + the rejected method instead of the stale "only `trio`" msg. - `runtime._runtime.Actor._from_parent`'s SpawnSpec-recv gate adds `'subint_forkserver'` to the existing `('trio', 'subint')` tuple — fork child-side runtime receives the same SpawnSpec IPC handshake as the others. - `subint_forkserver_proc` child-target now passes `spawn_method='subint_forkserver'` (was hard-coded `'trio'`) so `Actor.pformat()` / log lines reflect the actual parent-side spawn mechanism rather than masquerading as plain `trio`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- tractor/_root.py | 26 +++++++++++++++++++++++--- tractor/runtime/_runtime.py | 9 ++++++++- 2 files changed, 31 insertions(+), 4 deletions(-) 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()