stop the driver hanging on a terminal and on a launcher
ai-sandbox-autophase could sit forever, printing nothing, in two places that are both before the first unit -- which is why both looked like a script that "does nothing". The rc probe ran `timeout 15 bash -ic` in front of the user's terminal. An interactive bash calls tcsetpgrp() to take that terminal, is in its background, and is stopped for trying; a stopped process does not take SIGTERM, so the timeout waited in front of it and the driver waited on the command substitution behind it. It now runs in its own session (setsid), with stdin closed, under `timeout -k`, and reads the definition from a temp file rather than a pipe, because a grandchild an rc file leaves behind holds a pipe's EOF open long after the shell it came from has been reaped. A launcher is called *with* the run, and a function ending at `--env NAME` -- the shape everyone writes for typing by hand, including every example this repo printed -- discards the flags and the in-container command. The container then starts the image's default harness with no prompt and, with --no-interactive gone, the terminal attached: an agent waiting for keystrokes behind a pipe nobody reads. `ap_forwards_args` checks the captured definition, --status and the preflight name it with the one-line fix, and every child now starts with stdin on /dev/null so a launcher cannot put the sandbox back on the keyboard. Aliases and whole command lines need no forwarding: the shell appends the words to those. Tests: a launcher fixture that drops its arguments, one that leaves a process behind, and shape assertions on ap_probe_rc. LLM-Generated: true
This commit is contained in:
@@ -168,6 +168,27 @@ networking or the image, `make e2e` green too.
|
||||
contain quotes, newlines and `$` at once, so nothing may build that command line by
|
||||
concatenating raw text. The body is *never printed*: `ap_launcher_preview` names a
|
||||
function rather than echoing it, because its body is the `pass` call.
|
||||
- **The probe must not be able to touch, or wait on, the terminal.** It is
|
||||
`setsid` + `</dev/null` + `timeout -k 5 15` with the transcript in a **temp file**,
|
||||
and all three are load-bearing: an interactive bash started from a terminal calls
|
||||
`tcsetpgrp()`, is in that terminal's background, and is **stopped** for trying — and a
|
||||
stopped process does not take SIGTERM, so a plain `timeout` waited in front of it
|
||||
forever and the driver waited behind it before printing anything. A pipe is the other
|
||||
half: `$(...)` waits for EOF, which any grandchild the rc files leave behind (an
|
||||
agent, a helper daemon) holds open after `timeout` has reaped the shell it was
|
||||
watching. Only SIGKILL reaps a stopped process, hence `-k`. Read the definition into a
|
||||
file and none of that can hold the run. Tests: the shape assertions plus the
|
||||
backgrounding fixture in `tests/unit/10_autophase.sh`.
|
||||
- **A function launcher is called *with* the run, so it must forward its arguments.**
|
||||
Every child is `NAME --no-tty --no-interactive -- <in-container command>` with stdin
|
||||
on `/dev/null`; a function ending at `--env NAME` — the shape everyone writes for
|
||||
typing by hand — silently discards all of it, and the container then runs the image's
|
||||
default harness with no prompt, which on an attached terminal is an agent waiting for
|
||||
keystrokes behind a pipe nobody reads. `ap_forwards_args` checks the captured
|
||||
definition (aliases and command lines need it not: the shell appends), `--status` and
|
||||
the preflight name it, and every child starts `</dev/null` so the launcher cannot put
|
||||
the terminal back. Keep the `"$@"` in every launcher this repo prints — `install.sh`,
|
||||
`README.md`, `docs/recipes.md`.
|
||||
- **The push is the delivery contract.** `ap_push_pending` runs at start, at every
|
||||
phase boundary and at end of run; start is a warning, the boundary and the end are
|
||||
fatal, because exiting 0 with the work unpushed is the silent miss this script
|
||||
|
||||
Reference in New Issue
Block a user