fix(cnpg-drill): scan the manifest without a pipe, and name the real cause #154
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/drill-trap-no-pipe"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The archive trap's "flake" is SIGPIPE, and it was never a transient.
grep -qexits the instant it matches. The upstreamprintfis still writing, so it takes SIGPIPE and dies 141, andset -o pipefailreports the pipeline as 141 — for a successful match.if ...; thenreads 141 as false, so the guard announced "no archive destination" precisely when it had found one.Measured on this exact pattern — a 300k-line body matching on its first line:
40 runs out of 40. Small manifests usually finish writing before grep exits, which is why this presented as a flake rather than a hole: the two gate runs that failed today each accepted one archiving manifest at a different case, because those cases sit near the buffer threshold where the race is a coin flip.
A herestring has no upstream process to signal, so 0 / 1 / 2+ stay distinct.
On the earlier fixes
#151 and #152 were not wrong, and #152 already made this safe: its status check turns 141 into a refusal. But it refused with "the scan did not complete" rather than naming the archive destination — and crucially, a test that only asserts the exit status passes with the pipe restored and pins nothing. I caught that when my first attempt at this test went green against the broken code. The new case asserts which FATAL is printed.
Red: with the pipe restored, the large archiving manifest is refused for the wrong reason.
Green: it is named as archiving. Suite 45s, shellcheck clean.
https://claude.ai/code/session_01LeVatedQ4sCA1u6LHjo7B5
The archive trap's flake is not a transient. It is SIGPIPE. printf '%s\n' "$body" | grep -qE "$TRAP_BACKUP_RE" grep -q exits the instant it matches. The upstream printf is still writing, so it takes SIGPIPE and dies 141, and `set -o pipefail` reports the pipeline as 141 — for a SUCCESSFUL match. `if ...; then` reads 141 as false, so the guard announced "no archive destination" precisely when it had found one. Measured, on this exact pattern: a 300k-line body matching on its first line returned 141 on 40 runs out of 40, and 0 on none of them. Small manifests usually finish writing before grep exits, which is why it looked like a flake rather than a hole: the two seanfarm gate runs that failed today each accepted one archiving manifest at a DIFFERENT case, because those cases sit near the buffer threshold where the race is a coin flip. A herestring has no upstream process to signal, so 0/1/2+ stay distinct. The previous commit's status check already turned this into a refusal, so the trap was SAFE from that point on — but it refused with "the scan did not complete" instead of naming the archive destination, and a test that only checks the exit status passes with the pipe restored and pins nothing. The new case asserts WHICH FATAL is printed. Red: with the pipe restored, the large archiving manifest is refused for the wrong reason. Green: it is named as archiving. Suite 45s, shellcheck clean. Claude-Session: https://claude.ai/code/session_01LeVatedQ4sCA1u6LHjo7B5