Repository navigation
server: record an exit heard while reconnecting as reported, and fix a test's early terminate (P1R-C04 follow-up) - #111
Merged
Conversation
…a test's early terminate (P1R-C04 follow-up) Two P1R-C04 races that loops found while P1R-C05 was in CI, both on main too. An exit that the Runner reported right after its answer to a new Claim could reach the records before the client took the new connection as its own. The records then asked for the process's status, the client refused with RUNNER_RECONNECTING, and the records ended the process without saying how, which reconciliation does not correct. The records now ask again while the client refuses that way, and record the end as the Runner reports it once the gateway has claimed the Runner, which keeps the ended process until its end is recorded. A new test refuses the first status request that way; it failed before the change. an_independent_gateway_blocks_a_workspace_whose_records_and_runner_disagree terminated its sandboxed sleep right after starting it. A kill that lands while bubblewrap is still setting up the sandbox leaves the sandbox running under PID 1 with the output open, so the exit was not reported within the test's bound. The command now prints a line, and the test terminates it once it has read that line. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This was referenced Oct 15, 2026
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.
Requested by Seongjae · project thread
Issue
Part of #101: a follow-up to P1R-C04 (#105, #106) for two races that loops found while P1R-C05 (#108) was in CI, both on
mainbefore #108 too. The P1R lead thread asked for them in one PR, so that P1R-C06 qualifies amainwith both fixed. This PR does not close an issue: #109, the termination problem behind the test's race, stays open.mainatdadb58c, with P1R-C05 (#108) merged57908bc6e7e065; both unchangedSummary
Before:
RUNNER_RECONNECTING, and the records ended the process with no termination or exit code, which reconciliation does not correct.a_gateway_that_started_work_claims_its_runner_again_and_reconciles_itfailed this way in about 1 of 100 runs at 16 in parallel, onmainand on runner, server, store: answer for a lost Runner's processes and let an operator release them (P1R-C05) #108's branch.an_independent_gateway_blocks_a_workspace_whose_records_and_runner_disagreeterminated its sandboxedsleep 30about 100 ms after the Runner started it. When the kill landed while bubblewrap was still setting up the sandbox, the sandbox ran on under PID 1 with the Runner's output pipes open, so the Runner did not report the exit within the test's 20 s bound. It failed in 5 of 64 runs at 8 in parallel onmain, and failed runner, server, store: answer for a lost Runner's processes and let an operator release them (P1R-C05) #108's first Linux Integration job (comment).After:
RUNNER_RECONNECTING, and record the end as the Runner reports it once the gateway has claimed the Runner, which keeps the ended process until its end is recorded.How.
crates/server/src/records.rs:status_after_exitasks for the status of a process the Runner reported exited, and while the answer isRUNNER_RECONNECTINGasks again after 10 ms, then twice as long each time, up to 500 ms. Every other answer is handled as before. The client refuses that way only while it claims the Runner again; once it has lost the Runner or stopped trying, it refuses withRUNNER_DISCONNECTED, and the records end the process without saying how, as before.crates/server/src/mcp.rs, tests: the newan_exit_heard_while_claiming_again_is_recorded_as_the_runner_reports_it, and the command and the wait inan_independent_gateway_blocks_a_workspace_whose_records_and_runner_disagree.Contract changes
None: no tool schema, error code, status value or ID changes. A record of a process that exits as the gateway claims its Runner again now holds the termination and exit code the Runner reports, as process records already describe, instead of none.
Tests
Verified here at
57908bc, in a Linux cloud container running as root, on the Codex checkout with its recorded patch applied and the worker, patch and Linux sandbox binaries built:RUNNER_RECONNECTING, as the client does while it claims the Runner again, then with the exit. It passes, and without the change inrecords.rsit fails with the record the race left: terminal, no outcome, no exit code.mainbefore this change, the first failed in 1 of 96 runs at 16 at a time, and the second in 5 of 64 at 8 at a time.cargo fmt --checkfor the workspace and for the worker, andcargo clippy --locked --all-targets -- -D warningsin CI's six configurations.cargo test --locked --workspace: 447 passed, none failed.-p codespace-server --features devguard: 174 passed.-p codespace-domain --features devguard --lib: 34 passed. The worker: 11 passed, and 2 withdevguard.-p codespace-runner --features devguard --lib: 194 passed and 1 failed,launch::tests::nothing_is_committed_when_the_owner_cannot_launch, which fails only as root, as onmain; the same test binary passed it when run as an unprivileged user.python3 scripts/check_docs.py check(20 paired documents).Not verified here: the hosted macOS job, which CI runs.
Security scenarios
Out of scope