Retry gVisor agent startup crashes once before failing#6514
Conversation
There was a problem hiding this comment.
Pull request overview
Adds one-shot recovery for gVisor agent crashes caused by SIGABRT or SIGSEGV.
Changes:
- Retries gVisor exits 134/139 once.
- Preserves log continuity using
docker logs --since. - Passes the configured runtime into agent execution.
Show a summary per file
| File | Description |
|---|---|
src/container-lifecycle.ts |
Implements gVisor crash retry and log reattachment. |
src/run-agent-command.test.ts |
Tests retry and runtime scoping. |
src/commands/main-action.ts |
Wires the runtime into agent execution. |
src/commands/main-action.test.ts |
Tests runtime forwarding. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 4/4 changed files
- Comments generated: 2
- Review effort level: Medium
|
|
||
| if (isGvisorRuntime(containerRuntime)) { | ||
| for (let attempt = 1; attempt <= MAX_GVISOR_AGENT_RETRIES; attempt++) { | ||
| if (!GVISOR_RETRYABLE_AGENT_EXIT_CODES.has(exitCode)) { |
| stderr: 'inherit', | ||
| env: getLocalDockerEnv(), | ||
| }); | ||
| exitCode = await executeAgentAttempt(logsSince); |
|
@copilot address review feedback |
…dget - Add isGvisorStartupCrash() helper: uses docker inspect to measure container runtime; only containers that exit within 30s of start (GVISOR_STARTUP_CRASH_WINDOW_MS) are considered pure startup crashes safe to retry. This prevents a second run when the agent has already produced work (files, API calls, etc.). - Track a single overall deadline (overallDeadlineMs) in runAgentCommand before the first attempt. executeAgentAttempt now computes remainingMs = overallDeadlineMs - Date.now() on each call. When remainingMs <= 0 on the retry, the container is stopped immediately and exit code 124 is returned, so a gVisor run can never execute beyond the configured --agent-timeout total. - Update existing gVisor retry tests to supply the docker inspect mock (short runtime = startup crash). - Add new test: no retry when container ran past the 30s startup window. - Add new test: retry returns 124 immediately when overall budget is exhausted (verified via Date.now spy).
Both review items are addressed in commit a37a5e1: Startup-crash gating ( Single shared deadline ( |
|
✅ Build Test Suite completed successfully! |
|
Chroot tests passed! Smoke Chroot - All security and functionality tests succeeded. |
|
📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤 |
|
🛡️ Smoke Copilot Network Isolation confirmed the egress allowlist is enforced. ✅ |
|
✅ Contribution Check completed successfully! Contribution check complete: PR #6514 follows the applicable CONTRIBUTING.md guidelines. New gVisor retry functionality includes tests, the PR description is clear and references the related issue, and the files are organized appropriately. No review comment needed. |
|
🔌 Smoke Services — All services reachable! ✅ |
|
✅ Smoke Copilot BYOK completed. Copilot BYOK mode operational. 🔓 |
|
🔑 Smoke Copilot PAT PAT auth validated. All systems operational. ✅ |
|
✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟 |
|
✅ Smoke Claude passed |
|
📡 Smoke OTel Tracing completed. All tracing scenarios validated. ✅ |
🧪 Smoke Test Results
Overall: PASS
|
Smoke Test: Claude Engine Validation
Overall result: PASS
|
🔬 Smoke Test: Copilot PAT Auth
Overall: INDETERMINATE (template expansion failure)
|
|
Smoke test results
Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "registry.npmjs.org"See Network Configuration for more information.
|
Smoke Test: API Proxy OpenTelemetry Tracing
All 5 scenarios passed. OTEL tracing integration is working correctly.
|
Chroot Version Comparison Results
Overall: ❌ FAILED — Node.js version mismatch (host: v24.18.0, chroot: v22.23.1).
|
Smoke Test Results
Overall status: FAIL Warning Firewall blocked 1 domainThe following domain was blocked by the firewall during workflow execution:
network:
allowed:
- defaults
- "localhost"See Network Configuration for more information.
|
|
Smoke Test: Copilot BYOK (Direct) Mode
Status: PASS
|
Smoke Test: Services Connectivity — ❌ FAIL
|
🏗️ Build Test Suite Results
Overall: 8/8 ecosystems passed — ✅ PASS
|
|
Smoke test results:
Running in direct BYOK mode (COPILOT_PROVIDER_API_KEY + COPILOT_PROVIDER_BASE_URL) via api-proxy → Azure OpenAI (Foundry, o4-mini-aw) Overall: FAIL
|
|
|
🔍 Smoke Test: Docker Sbx Validation
Overall:
|
Under
sandbox.agent.runtime: gvisor, the agent occasionally dies before doing any work with native Node/V8 crashes (SIGABRT/exit 134 andSIGSEGV/exit 139). The same workloads were stable onruncanddocker-sbx, so this change focuses on recovering the known gVisor-specific hard-crash path instead of changing normal agent execution.Runtime-scoped recovery
containerRuntime.One-shot retry for native crash exits
runAgentCommand(), retry the agent container once when the gVisor runtime exits with:134(SIGABRT)139(SIGSEGV)docker start awf-agent, then reattaches log streaming and waits for the new exit status.Log continuity
docker logs --since <timestamp> -f awf-agenton the retry path to avoid replaying the full first-attempt log stream.CLI wiring