Hoist proc-title prefix to `_def_prefix` const

Make the sub-actor proc-title prefix a single
authoritative constant (`_proctitle._def_prefix`) so
the reap-recognition markers and `xontrib` banner pick
it up automatically — one place to flip the prefix
shape going fwd.

Deats,
- `_proctitle._def_prefix: str = '_subactor'`. New
  module-level const consumed by everything that needs
  to know the prefix.
- `set_actor_proctitle(actor, prefix=_def_prefix)`:
  takes an explicit `prefix` arg (default = the const)
  so callers can override per-spawn if they want.
- Default proc-title format:
  `'tractor[<reprol>]'` → `f'{prefix}[<reprol>]'`
  i.e. `_subactor[<reprol>]` by default.
- `_testing/_reap.py`: cmdline + comm markers source
  the prefix from `_proctitle._def_prefix` instead of
  the hardcoded `'tractor['`. So
  `_is_tractor_subactor()` tracks the const
  automatically.
- `xontrib/tractor_diag.xsh`: `acli.reap` orphan-mode
  banner now interpolates the
  `_TRACTOR_PROC_CMDLINE_MARKERS` tuple directly so
  the human-readable mode line stays in sync if the
  prefix shape changes again.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code

(cherry picked from commit 3a45dbd503)
wkt/tooling_enhancements_from_mtf_spawner
Gud Boi 2026-06-01 20:26:22 -04:00
parent 93558fe3c9
commit fd8d39c0ce
4 changed files with 46 additions and 27 deletions

View File

@ -8,9 +8,9 @@ after `Actor` construction, so any spawned sub-actor process
should: should:
- have `argv[0]` (== `/proc/<pid>/cmdline`) start with - have `argv[0]` (== `/proc/<pid>/cmdline`) start with
`tractor[<aid.reprol()>]` `<_def_prefix>[<aid.reprol()>]` (currently `_subactor[]`)
- have `/proc/<pid>/comm` start with `tractor[` (kernel - have `/proc/<pid>/comm` start with `<_def_prefix>[`
truncates to ~15 bytes) (kernel truncates to ~15 bytes)
- be detected as a tractor sub-actor by - be detected as a tractor sub-actor by
`_is_tractor_subactor(pid)` via the cmdline marker. `_is_tractor_subactor(pid)` via the cmdline marker.
@ -27,7 +27,10 @@ import trio
import tractor import tractor
from tractor.runtime._runtime import Actor from tractor.runtime._runtime import Actor
from tractor.devx._proctitle import set_actor_proctitle from tractor.devx._proctitle import (
set_actor_proctitle,
_def_prefix,
)
from tractor._testing._reap import ( from tractor._testing._reap import (
_is_tractor_subactor, _is_tractor_subactor,
_read_cmdline, _read_cmdline,
@ -41,8 +44,9 @@ _non_linux: bool = platform.system() != 'Linux'
def test_set_actor_proctitle_format(): def test_set_actor_proctitle_format():
''' '''
`set_actor_proctitle()` returns the canonical `set_actor_proctitle()` returns the canonical
`tractor[<aid.reprol()>]` form and actually mutates `<_def_prefix>[<aid.reprol()>]` form (currently
the running proc's title. `_subactor[]`) and actually mutates the running
proc's title.
''' '''
pytest.importorskip( pytest.importorskip(
@ -60,12 +64,14 @@ def test_set_actor_proctitle_format():
) )
title: str = set_actor_proctitle(actor) title: str = set_actor_proctitle(actor)
# canonical wrapping: `tractor[<aid.reprol()>]`. We # canonical wrapping: `<_def_prefix>[<aid.reprol()>]`.
# compare against the runtime-computed `reprol()` # We source BOTH the prefix (`_def_prefix`) and the
# rather than a hard-coded value so the test stays # runtime-computed `reprol()` rather than hard-coding,
# decoupled from `Aid.reprol()`'s internal format # so the test stays decoupled from the prefix shape
# (currently `<name>@<pid>`, but could evolve). # (flipped to `_subactor` in `3a45dbd5`) AND from
expected: str = f'tractor[{actor.aid.reprol()}]' # `Aid.reprol()`'s internal format (currently
# `<name>@<pid>`, but could evolve).
expected: str = f'{_def_prefix}[{actor.aid.reprol()}]'
assert title == expected assert title == expected
# sanity: the actor's name must be in the title # sanity: the actor's name must be in the title
# somewhere (so a future `reprol()` change that # somewhere (so a future `reprol()` change that
@ -140,15 +146,17 @@ def test_subactor_proctitle_visible_via_proc():
) )
pid, info = matched[0] pid, info = matched[0]
# canonical proctitle prefix in cmdline (full form) # canonical proctitle prefix in cmdline (full form);
assert info['cmdline'].startswith('tractor[proctitle_boi@'), ( # prefix sourced from `_def_prefix` so it tracks the
f'cmdline missing `tractor[proctitle_boi@…]` prefix: ' # `3a45dbd5` flip (`tractor[` -> `_subactor[`).
assert info['cmdline'].startswith(f'{_def_prefix}[proctitle_boi@'), (
f'cmdline missing `{_def_prefix}[proctitle_boi@…]` prefix: '
f'{info["cmdline"]!r}' f'{info["cmdline"]!r}'
) )
# comm is kernel-truncated to ~15 bytes — just check the # comm is kernel-truncated to ~15 bytes — just check the
# `tractor[` prefix made it. # `<_def_prefix>[` prefix made it.
assert info['comm'].startswith('tractor['), ( assert info['comm'].startswith(f'{_def_prefix}['), (
f'comm missing `tractor[` prefix: {info["comm"]!r}' f'comm missing `{_def_prefix}[` prefix: {info["comm"]!r}'
) )
# intrinsic-signal detector should match. # intrinsic-signal detector should match.
assert info['is_tractor'] is True assert info['is_tractor'] is True

View File

@ -90,7 +90,6 @@ keys are caller-defined).
''' '''
from __future__ import annotations from __future__ import annotations
import os import os
import pathlib import pathlib
import re import re
@ -99,6 +98,9 @@ import stat
import sys import sys
import time import time
from tractor.devx import _proctitle
# `/dev/shm` is the POSIX-shm filesystem on Linux + FreeBSD. # `/dev/shm` is the POSIX-shm filesystem on Linux + FreeBSD.
# macOS uses `shm_open` syscalls without a fs-visible path, # macOS uses `shm_open` syscalls without a fs-visible path,
# so the shm helpers refuse to run there. # so the shm helpers refuse to run there.
@ -230,9 +232,9 @@ def _read_comm(pid: int) -> str:
# while `cmdline` for zombies often reads as empty. # while `cmdline` for zombies often reads as empty.
_TRACTOR_PROC_CMDLINE_MARKERS: tuple[str, ...] = ( _TRACTOR_PROC_CMDLINE_MARKERS: tuple[str, ...] = (
'tractor._child', 'tractor._child',
'tractor[', _proctitle._def_prefix,
) )
_TRACTOR_PROC_COMM_MARKER: str = 'tractor[' _TRACTOR_PROC_COMM_MARKER: str = _proctitle._def_prefix
def _is_tractor_subactor(pid: int) -> bool: def _is_tractor_subactor(pid: int) -> bool:

View File

@ -24,7 +24,10 @@ which" at a glance without needing to read full
`/proc/<pid>/cmdline`. `/proc/<pid>/cmdline`.
Format: Format:
``tractor[<aid.reprol()>]`` e.g. ``tractor[doggy@1027301b]`` ``<_def_prefix>[<aid.reprol()>]`` e.g. ``_subactor[doggy@1027301b]``
(prefix from the `_def_prefix` const, flipped `tractor` ->
`_subactor` so sub-actor procs are visually distinct from the
root in `ps`/`htop` and the reap-recognition markers.)
Uses the canonical `Aid.reprol()` form Uses the canonical `Aid.reprol()` form
(``<name>@<uuid_short>``) so the proc-title matches the (``<name>@<uuid_short>``) so the proc-title matches the
@ -52,7 +55,13 @@ except ImportError:
_stp = None _stp = None
def set_actor_proctitle(actor: 'Actor') -> str | None: _def_prefix: str = '_subactor'
def set_actor_proctitle(
actor: 'Actor',
prefix: str = _def_prefix,
) -> str | None:
''' '''
Set the calling process's proc-title to identify it as a Set the calling process's proc-title to identify it as a
tractor sub-actor. tractor sub-actor.
@ -69,6 +78,6 @@ def set_actor_proctitle(actor: 'Actor') -> str | None:
if _stp is None: if _stp is None:
return None return None
title: str = f'tractor[{actor.aid.reprol()}]' title: str = f'{prefix}[{actor.aid.reprol()}]'
_stp.setproctitle(title) _stp.setproctitle(title)
return title return title

View File

@ -488,6 +488,7 @@ def _tractor_reap(args):
reap, reap,
reap_shm, reap_shm,
reap_uds, reap_uds,
_TRACTOR_PROC_CMDLINE_MARKERS,
) )
rc: int = 0 rc: int = 0
@ -500,9 +501,8 @@ def _tractor_reap(args):
else: else:
pids = find_orphans() pids = find_orphans()
mode = ( mode = (
'orphans (PPid==1, intrinsic ' f'orphans (PPid==1, intrinsic '
'cmdline/comm match — `tractor[…]` or ' f'cmdline/comm match — {_TRACTOR_PROC_CMDLINE_MARKERS}'
'`tractor._child`)'
) )
if not pids: if not pids: