CLI: a closed stdout pipe exits 141 silently (was E_INTERNAL); example avoids head under pipefail
Found by the P10 fresh-VM run: `simurg inspect … | head` raised BrokenPipeError, reported as an internal error, and stopped examples/gsa_demo.sh (set -o pipefail). run_guarded now flushes stdout inside the guard and maps BrokenPipeError to ExitCode.SIGPIPE (141) without a message. p10.sh: SKIP_DOCKER/SKIP_CONDA, clearer digest report; p10t.sh runs build+pip+tutorial only.
This commit is contained in:
1 parent
035e5ad66f
commit
522429b731
6 files changed
+38
-6
No files matched your search
@@ -7,6 +7,7 @@ Later phases add the other commands of CLI-001.
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
@@ -58,6 +59,11 @@ def run_guarded(reporter: Reporter, fn: Callable[[], int]) -> None:
|
||||
code = ExitCode.OK
|
||||
try:
|
||||
code = ExitCode(fn())
|
||||
sys.stdout.flush() # surface a closed pipe here, not at interpreter exit
|
||||
except BrokenPipeError:
|
||||
# the consumer of stdout stopped reading (`| head`): silence further writes, exit like a SIGPIPE'd tool
|
||||
os.dup2(os.open(os.devnull, os.O_WRONLY), sys.stdout.fileno())
|
||||
code = ExitCode.SIGPIPE
|
||||
except SimurgError as e:
|
||||
reporter.error(e.code, e.message + (f"\n hint: {e.hint}" if e.hint else ""), exc=e, file=e.path)
|
||||
code = e.exit_code
|
||||
|
||||
@@ -23,6 +23,7 @@ class ExitCode(IntEnum):
|
||||
PARTIAL = 3 # >= 1 sample failed and >= 1 succeeded
|
||||
ALL_FAILED = 4 # run completed but no sample succeeded
|
||||
SIGINT = 130
|
||||
SIGPIPE = 141 # the reader of stdout went away (e.g. `simurg inspect … | head`); nothing is reported
|
||||
SIGTERM = 143
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user