subagents, ACP: stop with SIGINT only, so claude ends its own tool commands
claude's Bash tool starts every command in a new session, so a signal to claude's process group never reaches it. claude stops those commands itself when SIGINT makes it shut down. A SIGKILL leaves them running, re-parented to init. Per the ruling on #4999, every stop is SIGINT and nothing escalates. - Subagent `interrupt` always sends SIGINT. The `force` argument is gone from the MCP tool and from `session::interrupt`. A caller that still sends `force: true` gets SIGINT; the argument is ignored. - `interrupt` used to free the session name before it signalled, so a `continue` could start a second claude on the session while the first was still exiting. The `running` map now holds a three-state `Slot` (starting, running, stopping). An interrupted claude turn is `Stopping` until the turn task's own `finish_turn` clears it. `status` says "stopping", and `start`/`continue` on that name are refused. `interrupt` still returns at once. The ACP arm is unchanged: its name is freed when `session/cancel` is sent. - ACP `Connection` drop sends its process group SIGINT, not SIGKILL, and the spawn no longer sets tokio's `kill_on_drop`, which SIGKILLed the leader after the `Drop` body. The test fixture's background grandchild resets SIGINT to default, since `&` starts it ignored. Tests: a fake claude that records SIGINT, interrupted, fails with `cancel(true)` (the old `force: true` path). An interrupted fake claude that keeps running keeps its name claimed and `continue` is refused, which fails when the slot is freed before the signal. A fake ACP agent that records SIGINT, dropped, fails with SIGKILL in `Drop`, and also with SIGINT in `Drop` but `kill_on_drop(true)` left in place. Not changed: hive-claude's idle watchdog (still SIGKILL, separate hive-claude change), the units' `KillSignal`, `machinectl kill`, and the login helper.
This commit is contained in:
parent
028c283ff9
commit
43e69d345e
7 changed files with 337 additions and 167 deletions
|
|
@ -35,13 +35,15 @@ The crate depends on no hyperhive binary crate, so `hive-agent` and
|
|||
A turn is stopped with `session/cancel`: by the `Canceller` handle, or by the
|
||||
idle watchdog once no `session/update` has arrived for
|
||||
`Config::idle_timeout`. An agent that has not answered the prompt 10s later
|
||||
is killed, and the next turn respawns it. A watchdog stop fails the turn
|
||||
with `AcpError::IdleTimeout` (`IdleKilled` if the agent was killed). This is
|
||||
is sent SIGINT, and the next turn respawns it. A watchdog stop fails the turn
|
||||
with `AcpError::IdleTimeout` (`IdleKilled` if the agent was sent SIGINT). This is
|
||||
the only way a provider error the agent retries without reporting it, such as
|
||||
an HTTP 429, ends the turn.
|
||||
|
||||
The agent leads its own process group. Killing it, and dropping the runtime,
|
||||
`SIGKILL`s that group, so the commands the agent started die with it.
|
||||
The agent leads its own process group. Stopping it, and dropping the runtime,
|
||||
sends that group SIGINT, so the commands the agent started get it too.
|
||||
Nothing escalates to SIGKILL: an agent that ignores SIGINT keeps running,
|
||||
and the next turn starts a new one beside it.
|
||||
|
||||
## ACP backend: compaction
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue