Add `use_stackscope` runtime var for subactor init

Track `stackscope` enablement in `RuntimeVars` so
the flag propagates to subactors via the standard
rtvar IPC path instead of relying solely on the
`TRACTOR_ENABLE_STACKSCOPE` env var.

Deats,
- add `use_stackscope: bool` to `RuntimeVars`
  struct + defaults dict
- `enable_stack_on_sig()` sets the rtvar on
  successful `stackscope` import, asserts unset
  on `ImportError`
- nest stackscope init under `_debug_mode` gate
  in `Actor.async_main`, check rtvar alongside
  env var
- defer `maybe_init_greenback` import to its own
  `use_greenback` branch

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
subint_forkserver_backend
Gud Boi 2026-04-30 20:50:07 -04:00
parent e2b790a70d
commit 48523358cf
3 changed files with 27 additions and 25 deletions

View File

@ -381,11 +381,13 @@ def enable_stack_on_sig(
message=r"coroutine method '(asend|athrow)' .* was never awaited", message=r"coroutine method '(asend|athrow)' .* was never awaited",
) )
import stackscope import stackscope
_state._runtime_vars['use_stackscope'] = True
except ImportError: except ImportError:
log.warning( log.warning(
'The `stackscope` lib is not installed!\n' 'The `stackscope` lib is not installed!\n'
'`Ignoring enable_stack_on_sig() call!\n' '`Ignoring enable_stack_on_sig() call!\n'
) )
assert not _state._runtime_vars['use_stackscope']
return None return None
# Capture the trio token if we're inside `trio.run` # Capture the trio token if we're inside `trio.run`

View File

@ -940,16 +940,13 @@ class Actor:
# `tractor._testing.pytest`'s `--enable-stackscope` # `tractor._testing.pytest`'s `--enable-stackscope`
# CLI flag — env var propagates via fork-inherited # CLI flag — env var propagates via fork-inherited
# environ). # environ).
import os if rvs['_debug_mode']:
if ( if (
rvs['_debug_mode'] rvs.get('use_stackscope')
or or
os.environ.get('TRACTOR_ENABLE_STACKSCOPE') os.environ.get('TRACTOR_ENABLE_STACKSCOPE')
): ):
from ..devx import ( from ..devx import enable_stack_on_sig
enable_stack_on_sig,
maybe_init_greenback,
)
try: try:
# TODO: maybe return some status msgs upward # TODO: maybe return some status msgs upward
# to that we can emit them in `con_status` # to that we can emit them in `con_status`
@ -966,6 +963,7 @@ class Actor:
) )
if rvs.get('use_greenback', False): if rvs.get('use_greenback', False):
from ..devx import maybe_init_greenback
maybe_mod: ModuleType|None = await maybe_init_greenback() maybe_mod: ModuleType|None = await maybe_init_greenback()
if maybe_mod: if maybe_mod:
log.devx( log.devx(

View File

@ -93,6 +93,7 @@ class RuntimeVars(Struct):
repl_fixture: bool|Callable = False # |AbstractContextManager[bool] repl_fixture: bool|Callable = False # |AbstractContextManager[bool]
# for `tractor.pause_from_sync()` & `breakpoint()` support # for `tractor.pause_from_sync()` & `breakpoint()` support
use_greenback: bool = False use_greenback: bool = False
use_stackscope: bool = False
# infected-`asyncio`-mode: `trio` running as guest. # infected-`asyncio`-mode: `trio` running as guest.
_is_infected_aio: bool = False _is_infected_aio: bool = False
@ -139,8 +140,9 @@ _RUNTIME_VARS_DEFAULTS: dict[str, Any] = {
# `debug_mode: bool` settings # `debug_mode: bool` settings
'_debug_mode': False, # bool '_debug_mode': False, # bool
'repl_fixture': False, # |AbstractContextManager[bool] 'repl_fixture': False, # |AbstractContextManager[bool]
# for `tractor.pause_from_sync()` & `breakpoint()` support
'use_greenback': False, 'use_greenback': False, # `.pause_from_sync()`/`breakpoint()`
'use_stackscope': False, # trio-task-stack dumps on SIGUSR1
# infected-`asyncio`-mode: `trio` running as guest. # infected-`asyncio`-mode: `trio` running as guest.
'_is_infected_aio': False, '_is_infected_aio': False,