From d28173f4c0fdc66fec5281cdd96d372889ea5bf8 Mon Sep 17 00:00:00 2001 From: goodboy Date: Wed, 17 Jun 2026 19:45:21 -0400 Subject: [PATCH] Make SIGUSR1 `stackscope` dumps actually work MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two fixes to the hang-debug SIGUSR1 task-tree dump path, surfaced by `/code-review high` on #462, - re-add `_debug_mode` to the sub-actor handler-install gate in `_runtime.py`. Dropping it (rel. `3a386ba5`/`3d9c75b6` "Drop debug_mode gate", from the `custom_log_levels_api` follow-up) was meant to *also* enable non-pdb runs, but nothing sets `use_stackscope` from `debug_mode`, so debug-mode subs were left with NO handler — and the default SIGUSR1 disposition then *kills* them. Now additive: `_debug_mode OR use_stackscope OR env`. - pass `write_file=True` at both `dump_task_tree()` SIGUSR1 call sites so the advertised `/tmp/tractor-stackscope-` `.log` tee is actually written (was dead under `--capture=fd`). Matches `1b1ef10a` "Re-enable writing `stackscope` to file by default"; param from `0df90500`. (this patch was generated in some part by [`claude-code`][claude-code-gh]) [claude-code-gh]: https://github.com/anthropics/claude-code --- tractor/devx/_stackscope.py | 4 ++-- tractor/runtime/_runtime.py | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/tractor/devx/_stackscope.py b/tractor/devx/_stackscope.py index 8e1605fd..35f22a49 100644 --- a/tractor/devx/_stackscope.py +++ b/tractor/devx/_stackscope.py @@ -248,7 +248,7 @@ def _dump_then_relay( ''' try: - dump_task_tree() + dump_task_tree(write_file=True) except BaseException: log.exception( '`dump_task_tree()` raised (scheduled via ' @@ -314,7 +314,7 @@ def dump_tree_on_sig( return else: - dump_task_tree() + dump_task_tree(write_file=True) except RuntimeError: log.exception( diff --git a/tractor/runtime/_runtime.py b/tractor/runtime/_runtime.py index 771eb49c..695090e1 100644 --- a/tractor/runtime/_runtime.py +++ b/tractor/runtime/_runtime.py @@ -930,20 +930,23 @@ class Actor: # TODO! -[ ] another `Struct` for rtvs.. rvs: dict[str, Any] = spawnspec._runtime_vars - # `stackscope` SIGUSR1 handler: install when EITHER - # `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` + # `stackscope` SIGUSR1 handler: install when ANY of + # `_debug_mode` / `use_stackscope` rt-vars OR the + # `TRACTOR_ENABLE_STACKSCOPE` env var is set (the + # latter being a 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 + # NOTE, NOT *exclusively* 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. + # runs too — but we DO still install under + # `_debug_mode` since otherwise the default SIGUSR1 + # action would terminate the proc, esp. nasty in + # infected-`asyncio` sub-actors mid-REPL. if ( + rvs.get('_debug_mode') + or rvs.get('use_stackscope') or os.environ.get('TRACTOR_ENABLE_STACKSCOPE')