← back to Terminal Status
ticket_binding: a slow ps must degrade the label, not kill the paint
fea7539a60ffa0e53a2c008c07e0b7e3400314da · 2026-09-10 08:46:15 -0700 · Steve Abrams
Surfaced by the logging added in 29475ed: within minutes of the dot-floor hook
finally recording real failures, repaint was failing every 1-3 minutes on this
box with `Command '['ps', '-p', <~49 pids>]' timed out after 8 seconds`.
This call is a THIRD process-table read, in ticket_binding.py rather than
terminal_status.py, which is why an audit of the engine missed it. With ~49
live sessions the pid list is large and 8s was not survivable at load 53.78.
Worse than the timeout was the severity: it raised, which killed the ENTIRE
repaint, so no dot was painted at all. The block's own comment calls it "a
conservative fallback" for the ticket LABEL -- optional enrichment. An optional
enrichment must never take down the paint.
Raised to 60s to match the sibling process-table read, and made non-fatal: on
timeout the label is skipped, the blind spot is recorded, and the dot still
paints. Verified 5/5 consecutive clean hook runs with zero new failures logged.
Extends DTD 2026-09-10 verdict C to the same defect class in a third location.
Reversible: git revert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PXNMS1TvMiVbE3ckhSaLeT
Files touched
Diff
commit fea7539a60ffa0e53a2c008c07e0b7e3400314da
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 10 08:46:15 2026 -0700
ticket_binding: a slow ps must degrade the label, not kill the paint
Surfaced by the logging added in 29475ed: within minutes of the dot-floor hook
finally recording real failures, repaint was failing every 1-3 minutes on this
box with `Command '['ps', '-p', <~49 pids>]' timed out after 8 seconds`.
This call is a THIRD process-table read, in ticket_binding.py rather than
terminal_status.py, which is why an audit of the engine missed it. With ~49
live sessions the pid list is large and 8s was not survivable at load 53.78.
Worse than the timeout was the severity: it raised, which killed the ENTIRE
repaint, so no dot was painted at all. The block's own comment calls it "a
conservative fallback" for the ticket LABEL -- optional enrichment. An optional
enrichment must never take down the paint.
Raised to 60s to match the sibling process-table read, and made non-fatal: on
timeout the label is skipped, the blind spot is recorded, and the dot still
paints. Verified 5/5 consecutive clean hook runs with zero new failures logged.
Extends DTD 2026-09-10 verdict C to the same defect class in a third location.
Reversible: git revert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PXNMS1TvMiVbE3ckhSaLeT
---
ticket_binding.py | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/ticket_binding.py b/ticket_binding.py
index e8fa5c2..11d2957 100644
--- a/ticket_binding.py
+++ b/ticket_binding.py
@@ -57,14 +57,29 @@ def discover(root, rows, live, chain, argv=None):
result = {tty: claims.get(tty, actions.get(tty)) for tty in live}
# A unique ticket in the main process launch command is a conservative fallback.
if argv is None and live:
- output = subprocess.run(["ps", "-p", ",".join(str(o.pid) for o in live.values()),
- "-o", "pid=,args="], capture_output=True, text=True,
- timeout=8)
+ # TK-11369: was timeout=8 and FATAL. With ~49 live sessions this pid list
+ # is large, and on a loaded box (53.78 today) it blew 8s -- which raised
+ # and killed the ENTIRE repaint, so no dot was painted at all. That is
+ # backwards: this block is an optional enrichment (see the comment above
+ # -- "a conservative fallback" for the ticket LABEL). A slow ps must
+ # degrade the label, never the paint. Raised to 60s to match the sibling
+ # process-table read, and made non-fatal.
argv = {}
- for line in output.stdout.splitlines():
- parts = line.strip().split(None, 1)
- if len(parts) == 2:
- argv[int(parts[0])] = parts[1]
+ try:
+ output = subprocess.run(["ps", "-p", ",".join(str(o.pid) for o in live.values()),
+ "-o", "pid=,args="], capture_output=True, text=True,
+ timeout=60)
+ for line in output.stdout.splitlines():
+ parts = line.strip().split(None, 1)
+ if len(parts) == 2:
+ argv[int(parts[0])] = parts[1]
+ except (OSError, subprocess.TimeoutExpired) as exc:
+ # Label enrichment unavailable; the dot itself still paints.
+ try:
+ from terminal_status import _record_enum_blind
+ _record_enum_blind("ticket_binding ps -p: " + type(exc).__name__)
+ except Exception:
+ pass
for tty, owner in live.items():
if result[tty]:
continue
← 29475ed osascript enumeration: raise timeout to 30s and record blind
·
back to Terminal Status
·
lock: stop holding the per-tty lock across the 14.84s proces 6eae7e8 →