mirror of
https://github.com/badlogic/pi-mono.git
synced 2026-11-05 23:37:25 +00:00
fix(coding-agent): let a started RPC or print shutdown finish; only a repeated signal forces exit (#11752)
Follow-up to #11746 for the case @fcatuhe reported on #11599: a second shutdown trigger cut off cleanup. Problem: Paseo stops pi by closing stdin and sending SIGTERM in the same tick (SIGKILL 2 s later); systemd sends SIGTERM and stdin closes after. In RPC mode: - stdin EOF, then SIGTERM: `shutdown()` removed pi's SIGTERM handler when it started, so the signal killed pi (exit 143) mid-`dispose()`. - SIGTERM, then stdin EOF: the second `shutdown()` call ran `process.exit()`. A pending MCP token refresh was lost: the server had rotated the refresh token, the next pi sent the old one, and the server revoked the grant. Rule after this change: once a shutdown has started, a stdin EOF or a single signal does not interrupt it; a second signal exits at once. SIGKILL still always works. - **RPC mode** (`rpc-mode.ts`): signal handlers stay registered until exit; `shutdown()` runs once and later calls do nothing; the signal handler counts signals and exits only on a repeated one. - **Print mode** (`print-mode.ts`): the final `finally` removed the signal handlers before `disposeRuntime()`, so a signal during the final disposal killed pi. Handlers are now removed after it, `disposeRuntime()` returns the shared in-flight disposal (a signal then waits for it), and a repeated signal exits at once, as before. - **Interactive mode**: unchanged. It already lets a started shutdown finish. Docs (`docs/rpc.md`) and the CHANGELOG are updated. ## Testing - `test/rpc-prompt-response-semantics.test.ts`: EOF then SIGTERM, SIGTERM then EOF (both wait for a slow dispose, exit once with 0 and 143), and EOF then two SIGTERMs (exits at once with 143). All three fail on main. - `test/print-mode.test.ts`: SIGTERM during the final disposal waits for it, a second SIGTERM exits with 143, handlers are removed afterwards. Fails on main. - Real process, `pi --mode rpc` with a `session_shutdown` handler that takes 1 s and real signals: - EOF then SIGTERM: cleanup done, exit 0 (main: no cleanup, exit 143) - SIGTERM then EOF: cleanup done, exit 143 - EOF then two SIGTERMs: exit 143 at once - `npm run check` passes; all `test/rpc*` and `test/print-mode` tests pass.
This commit is contained in:
parent
efb45b51d4
commit
ace560c302
6 changed files with 167 additions and 26 deletions
|
|
@ -92,6 +92,8 @@ Clients must also handle child-process startup failures, unexpected exits, stder
|
|||
|
||||
Close the child's stdin to request an orderly shutdown. Pi disposes the active runtime before exiting. Clients should still handle process signals and unexpected exits.
|
||||
|
||||
SIGTERM and SIGHUP also start an orderly shutdown. Once a shutdown has started, from either stdin EOF or a signal, a stdin EOF or a single signal does not interrupt it; a second signal exits at once. Closing stdin and sending SIGTERM together is safe.
|
||||
|
||||
An extension can also request shutdown with `ctx.shutdown()`. If the session is idle and no command is being handled, Pi shuts down right away. Otherwise it shuts down once the current command finishes (for `prompt`, once the prompt settles) or the active run emits `agent_settled`. (A request made while an extension-started compaction is running waits for the next command or run to finish.)
|
||||
|
||||
## Minimal client
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue