fix: cancel disconnected exec sessions and clean up docs - #14
Merged
Merged
Conversation
The process-group kill runs on cancel only, so a daemonized grandchild survives a normal exit by design; clearing the decoded entropy leaves the scanner's copy, so the comment no longer promises a heap free of it.
Keep reading the connection after stdin closes and cancel the child when the reader exits, including clean EOF. Add regressions for quiet children with open and closed stdin while the server context remains live.
…r order cmd.Stdout is a writer, so the copier Start spawns can forward the child's first output before runExec encodes MsgStarted; the test asserted a fixed order the code does not promise.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Whole-repo review round, 2026-09-21. Every production file read in full; the host→guest exec flow (cocoon
vm exec→ hybrid vsock → agent → child → framed reply), the reseed path and the Windows transport were traced end to end by a reader agent that ran eleven probes (framing edges, 1 MiB output, non-zero exit, ctx kill, mid-stream connection drop, 200 KiB stdin, 16 concurrent sessions, a real reseed with both RNG ioctls in a privileged Linux container); a docs lens verified every claim on all seven pages; a tests lens read the five test files.Commits
07a2edfreview: two comments claim less than they did6be436freview: remove dead code and align documentation5d41245fix: cancel active exec sessions on disconnect89aa3b6test: the disconnect test takes the started and ready frames in either orderFindings
agent/sysproc_linux.gosleep 6 &alive after a clean exit)agent/reseed_linux.gocmd/transport_windows.goLocalAddr5d41245changes no frameagent/agent.gohandleConn(found by the owner after the round)MsgStdinCloseand, on a clean EOF, returned without cancelling the child, so a client that vanished after closing stdin (or while a quiet child ran) left the child running until it exited or the server context ended; the round's read recorded that the reader exits, not that the child outlives the client, and the disconnect probe dropped the connection only while output was flowing5d41245: the reader drains the connection after stdin closes and cancels the exec context whenever it exits;TestExecDisconnectCancelsQuietChildfails on the pre-fix code (both subtests time out) and passes on HEAD; the exec-flow lens measured the same on archives of both trees (a quiet child whose client vanished after closing stdin is alive 5 s later on the old tree, reaped at once on the new one) and re-ran its nine exec probes unchanged. Host consumers (cocoon vm execthrough this repo's client package) never half-close, so an EOF at the agent means the client is goneclient/client.goRun,packaging/install-cocoon-agent.ps1sawExitbranch the read loop could never reach, and an unused$binPathvariable; the LOC lens reported no dead code6be436fDocs: all seven pages verified against source in the round;
6be436f/5d41245then reshaped README.md (highlights, related projects, Makefile targets, all checked against the Makefile) and the architecture page's error and StdinClose bullets, both checked againsthandleConn(an undecodable first frame is logged unless it is a plain EOF and the connection closed without a frame;MsgStdinCloseends input, not the session).Design notes (owner decision, no code)
MsgExitnow loses its child: since5d41245an EOF on the connection cancels the session. No shipped caller does this (the client package only closes the whole connection, on context cancel), and the architecture page's new StdinClose sentence states the input side; if the guarantee is worth spelling out, one clause on that bullet ("closing the connection ends the session and the command") does it.Cut-list (report only)
The owner's
6be436fcut the two dead items the LOC lens missed (sawExit,$binPath); nothing else is on the list — the standing rejections (Winsocksend()==0guard,Message.PID, the two vsock reject loops,processController,len(argv)==0) stand.LOC (same counting on both ends)
Per commit:
07a2edfreview 2/2 (comments +1/−1);6be436freview 0/14 (comments +0/−6);5d41245fix 10/7 · 83/0 (comments +4/−4);89aa3b6test 0/0 · 17/8.Gates
All gates re-run on HEAD
89aa3b6(and on5d41245before the test commit):GOWORK=off make fmt-check: rc=0;golangci-lintonGOOS=darwin,linuxandwindows: 0 issues;GOOS=windows go vet: ok.asl ./...on darwin and linux: 0 findings.go test -race -count=1 ./...: green (agent, client on darwin).TestExecDisconnectCancelsQuietChildrun against the pre-fixagent/agent.go: both subtests fail (5 s timeouts), so the test is red before the fix and green after; at HEAD it passes-race -count=30.golang:1.27container:go build ./... && go vet ./... && go test -race -count=1 ./...green (agent, client, cmd) on5d41245and89aa3b6.Codex
Round 1, thread
01a0c25f-d040-70c0-9e66-fe627417b63d, read-only sandbox, on HEAD07a2edf; the prompt carried the discipline (no contrived scenarios, no over-design, idempotent fixes, no over-defense). Final message, verbatim:Round 2 on
5d41245(the owner's two commits, same thread): the production fix judged sound; one finding on the new test, verbatim:Confirmed from
runExec(cmd.Stdoutis a writer, so the copierStartspawns races theMsgStartedencode) and fixed by89aa3b6.Round 3 on
89aa3b6, verbatim:Follow-ups
None filed.