fix: discard-dist-on-failure keeps the step's status when its message cannot be written (closes #342)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

With stderr closed, the wrapper's message write failed and set -e ended it
with status 2; with stderr a pipe whose reader had gone, the write killed it
with 141. The message is now written with SIGPIPE ignored and its failure
ignored, after the step has run. An interrupt while a step runs now exits with
130 once the step has ended, removing nothing: under bash, a step that caught
the interrupt and exited with a status, as check-censored does, used to get
dist/ removed. A failed check-censored --require-dist still removes dist/. The
header states both. Also the README bullet's missing period.

Model: opus-5-5
This commit is contained in:
2026-10-07 01:43:43 +00:00
parent 1cfd69e72d
commit dbdc416e77
4 changed files with 108 additions and 17 deletions
+70
View File
@@ -915,6 +915,76 @@ run_cases() {
discard_case "the wrapper given no command removes nothing" \
c_control 1 kept "no command given" ""
# With stderr closed the wrapper cannot write its message, and must still
# remove dist/ and return the step's own status.
build_fixture
_status=0
(cd "$FIXTURE" &&
"$FIXTURE/script/discard-dist-on-failure" sh -c 'exit 6' 2>&-) ||
_status=$?
if [ "$_status" -eq 6 ] && [ ! -e "$FIXTURE/dist" ]; then
PASSED=$((PASSED + 1))
echo " ok: a failed step's status survives a closed stderr"
else
FAILED=$((FAILED + 1))
echo " FAIL: a failed step's status survives a closed stderr"
echo " exit status $_status, wanted 6, and dist/ must be gone"
fi
# The same with stderr a pipe nobody reads any more, where the write would
# kill the wrapper with SIGPIPE. The FIFO's only reader opens it, exits and
# is waited for before the wrapper runs, so the pipe never has a reader.
build_fixture
mkfifo "$WORK/stderr-fifo"
_status=0
(
: <"$WORK/stderr-fifo" &
exec 3>"$WORK/stderr-fifo"
wait "$!"
cd "$FIXTURE" &&
"$FIXTURE/script/discard-dist-on-failure" sh -c 'exit 6' 2>&3
) || _status=$?
if [ "$_status" -eq 6 ] && [ ! -e "$FIXTURE/dist" ]; then
PASSED=$((PASSED + 1))
echo " ok: a failed step's status survives a pipe nobody reads"
else
FAILED=$((FAILED + 1))
echo " FAIL: a failed step's status survives a pipe nobody reads"
echo " exit status $_status, wanted 6, and dist/ must be gone"
fi
# An interrupt while a step runs removes nothing and says nothing, even
# when the step catches it and exits with a status of its own, as
# script/check-censored does. The step interrupts the wrapper and then
# itself, as Ctrl-C interrupts every process of the build at once. Run
# under dash and under bash, which /bin/sh may each be: bash carries on
# after such a step unless the wrapper stops it.
for _shell in dash bash; do
_name="an interrupt under $_shell removes nothing"
if ! command -v "$_shell" >/dev/null 2>&1; then
SKIPPED=$((SKIPPED + 1))
SKIPPED_NAMES="$SKIPPED_NAMES## - $_name ($_shell not found)$NEWLINE"
echo " SKIP ($_shell not found): $_name"
continue
fi
build_fixture
_status=0
_out="$(cd "$FIXTURE" && "$_shell" \
"$FIXTURE/script/discard-dist-on-failure" \
sh -c 'trap "exit 4" INT; kill -INT "$PPID" $$; exit 5' 2>&1)" ||
_status=$?
if [ "$_status" -eq 130 ] && [ -z "$_out" ] &&
[ -f "$FIXTURE/dist/chrome/src/popup/index.js" ]; then
PASSED=$((PASSED + 1))
echo " ok: $_name"
else
FAILED=$((FAILED + 1))
echo " FAIL: $_name"
echo " exit status $_status, wanted 130; dist/ must be intact" \
"and nothing said. Output: $_out"
fi
done
check_makefile_wiring
}