← back to Terminal Status
fix: raise process-table timeout so dot painting survives a busy box
63f3fae001f9b8ec2758058855bddf78cc2e6208 · 2026-09-10 07:58:58 -0700 · Steve Abrams
`ps -ax` costs ~4-5s idle and ~30s under load on this workstation (~2k
processes from the MCP fleet), so the 8s ceiling in processes() was
marginal at rest and failed outright whenever anything ran in parallel --
every color-dot script died with "timed out after 8 seconds" and no tab
could be painted at all. Raise to 60s and convert the bare TimeoutExpired
into an actionable StatusError. The full table is genuinely required
(owners() proves a tty has exactly ONE live runtime before agreeing to
paint it), so this is headroom, not a narrower query.
Verified: 26/26 tests pass; current.sh now resolves ttys022 in 9.2s.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHKdiEfwLNDHqKgMRbBNS2
Files touched
Diff
commit 63f3fae001f9b8ec2758058855bddf78cc2e6208
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 10 07:58:58 2026 -0700
fix: raise process-table timeout so dot painting survives a busy box
`ps -ax` costs ~4-5s idle and ~30s under load on this workstation (~2k
processes from the MCP fleet), so the 8s ceiling in processes() was
marginal at rest and failed outright whenever anything ran in parallel --
every color-dot script died with "timed out after 8 seconds" and no tab
could be painted at all. Raise to 60s and convert the bare TimeoutExpired
into an actionable StatusError. The full table is genuinely required
(owners() proves a tty has exactly ONE live runtime before agreeing to
paint it), so this is headroom, not a narrower query.
Verified: 26/26 tests pass; current.sh now resolves ttys022 in 9.2s.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MHKdiEfwLNDHqKgMRbBNS2
---
terminal_status.py | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/terminal_status.py b/terminal_status.py
index 8cc6e20..4cab0a8 100644
--- a/terminal_status.py
+++ b/terminal_status.py
@@ -97,10 +97,24 @@ class Process:
def processes():
- result = subprocess.run(
- ["ps", "-axo", "pid=,ppid=,tty=,lstart=,comm="],
- capture_output=True, text=True, timeout=8,
- env={**os.environ, "LC_ALL": "C"})
+ # `ps -ax` walks the whole process table, so its cost scales with how many
+ # processes the box is running -- on a workstation with a large MCP fleet
+ # (~2k procs) it measures ~4-5s idle and ~30s under concurrent load. The old
+ # 8s ceiling was marginal even at rest, so any parallel work turned it into
+ # a hard failure: every dot script died with "timed out after 8 seconds"
+ # and no tab could be painted at all.
+ # Ownership resolution genuinely needs the full table (owners() proves a
+ # tty has exactly ONE live runtime before we agree to paint it), so the fix
+ # is headroom plus an actionable message, not a narrower query.
+ try:
+ result = subprocess.run(
+ ["ps", "-axo", "pid=,ppid=,tty=,lstart=,comm="],
+ capture_output=True, text=True, timeout=60,
+ env={**os.environ, "LC_ALL": "C"})
+ except subprocess.TimeoutExpired:
+ raise StatusError(
+ "Timed out reading the process table (ps -ax took >60s); the box is "
+ "overloaded -- check the process count with `ps -A | wc -l`.")
if result.returncode:
raise StatusError("Cannot inspect live terminal owners: " + result.stderr.strip())
rows = {}
← 914a88d fix: paint guard resolves ancestry before refusing on CLAUDE
·
back to Terminal Status
·
set: automatic paints yield to sticky semantic dots (orange/ e6a426b →