From 3d9c75b6ed6e2d12fbffc7fb63c0bf0779d9c2b3 Mon Sep 17 00:00:00 2001 From: goodboy Date: Thu, 28 May 2026 18:35:40 -0400 Subject: [PATCH] Drop `debug_mode` gate on stackscope SIGUSR1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SIGUSR1 task-tree dumps via `stackscope` should work in plain (non-pdb) runs too — esp. in infected-`asyncio` processes where the kernel-default SIGUSR1 disposition is `Term` (proc dies on `kill -USR1` w/o an installed handler). Ungate the install path from `_debug_mode` in both root and sub-actor init; the `use_stackscope` rt-var + `TRACTOR_ENABLE_STACKSCOPE` env-var checks remain as the actual opt-in (e.g. via `--enable-stackscope`). Deats, - `_root.open_root_actor`: drop the `debug_mode and ...` conjunction around the `enable_stack_on_sig()` call; now gated only on the `enable_stack_on_sig` arg itself. - `_runtime.Actor` sub-actor init: lift the `use_stackscope`/`TRACTOR_ENABLE_STACKSCOPE` branch out of the `if rvs['_debug_mode']:` block to peer-level. The `use_greenback` branch stays inside `_debug_mode` (pdb-specific). - Refresh inline comments on both sites to call out the infected-`asyncio` "default SIGUSR1 = terminate proc" rationale. (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 | 11 ++++---- tractor/runtime/_runtime.py | 54 ++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/tractor/_root.py b/tractor/_root.py index 3bfe7b9f..78a1be56 100644 --- a/tractor/_root.py +++ b/tractor/_root.py @@ -435,11 +435,12 @@ async def open_root_actor( ) # TODO: factor this into `.devx._stackscope`!! - if ( - debug_mode - and - enable_stack_on_sig - ): + # + # NOTE, intentionally NOT gated on `debug_mode` so SIGUSR1 + # task-tree dumps work in plain (non-pdb) runs too — esp. + # in infected-`asyncio` root processes where the default + # SIGUSR1 action would otherwise terminate the proc. + if enable_stack_on_sig: from .devx._stackscope import enable_stack_on_sig enable_stack_on_sig() diff --git a/tractor/runtime/_runtime.py b/tractor/runtime/_runtime.py index 1111d30f..fc0100ab 100644 --- a/tractor/runtime/_runtime.py +++ b/tractor/runtime/_runtime.py @@ -934,34 +934,40 @@ class Actor: rvs: dict[str, Any] = spawnspec._runtime_vars # `stackscope` SIGUSR1 handler: install when EITHER - # `_debug_mode=True` (full multi-actor pdb support - # path) OR the `TRACTOR_ENABLE_STACKSCOPE` env var - # is set (lighter test-time hang-debug path; see + # `use_stackscope` is set in rt-vars OR the + # `TRACTOR_ENABLE_STACKSCOPE` env var is set (lighter + # test-time hang-debug path; see # `tractor._testing.pytest`'s `--enable-stackscope` # CLI flag — env var propagates via fork-inherited # environ). + # + # NOTE, intentionally NOT gated on `_debug_mode` so + # SIGUSR1 task-tree dumps work in plain (non-pdb) + # runs too — esp. in infected-`asyncio` sub-actors + # where the default SIGUSR1 action would otherwise + # terminate the proc. + if ( + rvs.get('use_stackscope') + or + os.environ.get('TRACTOR_ENABLE_STACKSCOPE') + ): + from ..devx import enable_stack_on_sig + try: + # TODO: maybe return some status msgs upward + # to that we can emit them in `con_status` + # instead? + log.devx( + 'Enabling `stackscope` traces on SIGUSR1' + ) + enable_stack_on_sig() + + except ImportError: + log.warning( + '`stackscope` not installed for use in ' + 'debug mode / `--enable-stackscope`!' + ) + if rvs['_debug_mode']: - if ( - rvs.get('use_stackscope') - or - os.environ.get('TRACTOR_ENABLE_STACKSCOPE') - ): - from ..devx import enable_stack_on_sig - try: - # TODO: maybe return some status msgs upward - # to that we can emit them in `con_status` - # instead? - log.devx( - 'Enabling `stackscope` traces on SIGUSR1' - ) - enable_stack_on_sig() - - except ImportError: - log.warning( - '`stackscope` not installed for use in ' - 'debug mode / `--enable-stackscope`!' - ) - if rvs.get('use_greenback', False): from ..devx import maybe_init_greenback maybe_mod: ModuleType|None = await maybe_init_greenback()