fix: spawn-test stderr persistence and drain-cap deadlock (PR #11 review)
Two bugs caught in supervisor review: 1. Stderr was silently dropped when the Details panel was closed during a crash. _on_spawn_done appended to diag_text only when the panel was already open, and refresh_dependency() clobbered that text on the next field change anyway. Fix: stash the result in self._last_spawn; _full_diag_text() appends the stderr section whenever diag text is generated; _on_spawn_done auto-opens the panel on non-ok outcomes (same pattern as the existing auto_open for missing commands). 2. _drain stopped reading once _STDERR_CAP (4 KB) was reached. A process that writes more than 4 KB then blocked on a full pipe buffer, never exited, and was misclassified as "ok" instead of "crashed". Fix: drain to EOF unconditionally; keep only the first _STDERR_CAP bytes. Regression test: 64 KB stderr + exit(3) → outcome "crashed". Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+8
-2
@@ -1114,12 +1114,18 @@ def spawn_test(data: dict, timeout: float = 3.0) -> dict:
|
||||
stderr_chunks: list[bytes] = []
|
||||
|
||||
def _drain(pipe) -> None:
|
||||
# Read until EOF so the pipe buffer never fills and blocks the subprocess.
|
||||
# Only keep the first _STDERR_CAP bytes; the rest is discarded.
|
||||
captured = 0
|
||||
try:
|
||||
while sum(len(c) for c in stderr_chunks) < _STDERR_CAP:
|
||||
while True:
|
||||
chunk = pipe.read(1024)
|
||||
if not chunk:
|
||||
break
|
||||
stderr_chunks.append(chunk)
|
||||
if captured < _STDERR_CAP:
|
||||
keep = min(len(chunk), _STDERR_CAP - captured)
|
||||
stderr_chunks.append(chunk[:keep])
|
||||
captured += keep
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user