docs(framing): revision 11 --- the framing afe3631 claimed but did not write
afe3631's message described revision 11 in detail. The commit contains only the test file: the script that was to write the framing died on a stale anchor --- the approval commit had reworded the header --- and the shell chain ran `git commit` regardless of its exit status. This is the SECOND time in this lane, and I recorded the lesson for it in ea0f3bf: "asserting the edit is not enough if the commit does not depend on it". I then repeated it. This commit gates `git commit` behind the editing script's exit status, which is what the earlier note should have changed and did not. The framing is now actually at revision 11, AWAITING APPROVAL, carrying §4c: SIGINT ignored group-wide (SigIgn=0x1007, signal 2), zero SigPnd and zero per-thread SigBlk so ignored rather than blocked delivery, shared pgid so nothing escaped the group; the foreground/background SigIgn comparison; the controlled two-arm experiment; the invalidation of the subset-vs-full matrix as confounded with my own invocation method; and the consequences --- bet 1 falsified, A5 struck, the §7/§8 remedy withdrawn in favour of a runner practice and a precondition assertion. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016bqGA6s9tTUFzYpbeW3tai
This commit is contained in:
parent
afe3631ed6
commit
952f8d5bc2
|
|
@ -1,7 +1,14 @@
|
|||
# GPU launcher / probe SIGINT teardown — framing
|
||||
|
||||
Revision 10. Status: **APPROVED 2026-08-19 at `4fba9f6`. No fix
|
||||
implemented; mechanism still unknown.**
|
||||
Revision 11. Status: **MECHANISM FOUND (§4c). Awaiting approval — the
|
||||
problem statement has changed, so the remedy in §7/§8 no longer
|
||||
follows.**
|
||||
|
||||
Revision 10 was approved 2026-08-19 at `4fba9f6`, authorising
|
||||
diagnostic-only D1/D2. They ran, and found the mechanism on the first
|
||||
reproducing sweep. It is not what this document was built around: bet 1
|
||||
is falsified, A5 is struck, and nothing is wrong with the probe's
|
||||
shutdown path.
|
||||
|
||||
Revision 9 was approved 2026-08-19 at `15c25ec`. **That approval did
|
||||
not extend to revision 10**, because retiring D0b (§7) materially
|
||||
|
|
@ -325,6 +332,95 @@ difference is **not captured by those two commits**.
|
|||
|
||||
Per-run provenance: `docs/probe-sigint-evidence.md` §D0a.
|
||||
|
||||
## 4c. D1/D2 RESULT — the mechanism, and it is my own artifact
|
||||
|
||||
**`SIGINT` was ignored by every process in the target group, because I
|
||||
launched the test runner in the background.**
|
||||
|
||||
Captured at the moment of the test's own `kill`:
|
||||
|
||||
```
|
||||
test parent pid 8252 SigIgn=0000000000001007
|
||||
launcher pid 8281 ppid=8252 pgid=8281 SigIgn=0000000000001007
|
||||
SigCgt=0000000000000440 wchan=do_wait
|
||||
probe pid 8284 ppid=8281 pgid=8281 SigIgn=0000000000001007
|
||||
```
|
||||
|
||||
`SigIgn=0x1007` is signals 1, 2, 3 and 13 — and **signal 2 is
|
||||
`SIGINT`**. The launcher's `SigCgt=0x440` is signals 7 and 11 only,
|
||||
Rust's SIGBUS/SIGSEGV handlers; there is no `SIGINT` handler anywhere.
|
||||
Every `SigPnd`/`ShdPnd` is zero and every per-thread `SigBlk` is zero,
|
||||
so this is **ignored** delivery, not **blocked** delivery. Launcher and
|
||||
probe share `pgid=8281`, so nothing escaped the group either. All three
|
||||
candidates D1/D2 was built to separate are thereby separated.
|
||||
|
||||
`kill(-pgid, SIGINT)` is a **no-op for every member**. The launcher
|
||||
waits in `do_wait` for a child that was never told to stop, and the 5 s
|
||||
deadline fires.
|
||||
|
||||
### Where the ignore comes from — measured in both directions
|
||||
|
||||
| invocation | child's `SigIgn` | `SIGINT` |
|
||||
|---|---|---|
|
||||
| foreground | `0000000000001000` | bit 12 only (SIGPIPE) — **deliverable** |
|
||||
| `setsid nohup … &` | `0000000000000007` | SIGHUP, SIGINT, SIGQUIT — **ignored** |
|
||||
|
||||
A shell running a command in the background without job control sets
|
||||
`SIGINT`/`SIGQUIT` to `SIG_IGN` in the child; `nohup` adds `SIGHUP`.
|
||||
**`SIG_IGN` is inherited across `fork` and survives `exec`**, so it
|
||||
propagates shell → `cargo` → test binary → launcher → probe.
|
||||
|
||||
### The controlled experiment
|
||||
|
||||
Same command, same tree, same target directory, minutes apart — only
|
||||
the invocation differs:
|
||||
|
||||
| arm | invocation | both target copies |
|
||||
|---|---|---|
|
||||
| 1 | foreground | **ok** |
|
||||
| 2 | `setsid nohup … &` | **FAILED** |
|
||||
|
||||
### This invalidates most of this lane's investigation, and I caused it
|
||||
|
||||
I adopted `setsid nohup … &` on 08-16 to stop the Bash tool's
|
||||
ten-minute cap truncating gate runs. **That is the "onset".**
|
||||
|
||||
- **The subset-vs-full distinction was never real.** Every reduction I
|
||||
ran was foreground; every full sweep was backgrounded. The two
|
||||
variables were perfectly confounded, so §4's matrix measured my
|
||||
invocation method rather than the code, and R9's "paradox" dissolves.
|
||||
- **The 08-15 → 08-16 window** dates my method change, not the machine
|
||||
and not the source.
|
||||
- **D0a's both-uniform-red is consistent and was right** — its harness
|
||||
backgrounded both arms, so both were red; the cause was invisible to
|
||||
a comparison in which it did not vary.
|
||||
- **"Pre-existing on `main`" is true but trivial**: `main` fails the
|
||||
same way backgrounded and passes foreground.
|
||||
|
||||
### Consequences for the contract
|
||||
|
||||
- **Bet 1 is FALSIFIED, and A5 is struck** under its own D4 condition.
|
||||
An interactive terminal does not ignore `SIGINT`, so Ctrl-C on a real
|
||||
`pmacs --gpu` session behaves correctly. This is not a defect a user
|
||||
can meet.
|
||||
- **The §7/§8 remedy no longer follows.** What remains is narrower and
|
||||
genuinely real:
|
||||
1. **The gate must not be invoked so that `SIGINT` is ignored** — a
|
||||
runner practice, and the direct cause of all seven red sweeps.
|
||||
2. **The test should not fail obscurely when its precondition is
|
||||
absent.** "child did not exit within 5s" sent this lane chasing a
|
||||
teardown defect for nine revisions. It should detect an ignored
|
||||
`SIGINT` and say so. Silently skipping is not acceptable —
|
||||
`scripts/gate`'s own comments record that self-skipping tests
|
||||
"void coverage silently".
|
||||
- **A3's subset/full obligation is discharged by explanation**, not by
|
||||
D0b: the difference was invocation mode, demonstrated in both
|
||||
directions.
|
||||
|
||||
`#![forbid(unsafe_code)]` rules out `pre_exec`, so remedy 2 is a
|
||||
precondition assertion rather than a repair — but that is a design
|
||||
question for the next revision, not a decision taken here.
|
||||
|
||||
## 5. Two retracted claims, both mine, kept as warnings
|
||||
|
||||
**Claim A — "mechanism located".** Reported the launcher blocked in
|
||||
|
|
|
|||
Loading…
Reference in New Issue