Antigravity: reap MCP servers left behind by the usage probe - #4077
bcharleson wants to merge 3 commits into
Conversation
agy -p /usage starts the user's MCP servers in a private temp directory and then exits. Servers that call setsid are reparented to launchd and keep a core busy after every refresh. Record descendants while the probe is alive, and kill anything still using that directory once it finishes.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs real behavior proof before merge. Reviewed September 27, 2026, 10:30 PM ET / September 28, 2026, 02:30 UTC (Revision 2). ClawSweeper reviewWhat this changesThe PR tracks processes started by Antigravity’s CLI usage probe and stops surviving descendants or processes still using the probe’s temporary directory. Merge readiness⛔ Blocked before merge - 6 items remain The cleanup is still useful because current main does not reap detached MCP servers after a successful Antigravity usage probe. The updated head fixes the previously reported child PID escalation gap, but the parent PID can still be reused while descendant polling continues, and the supplied macOS trace does not show the process observations needed to verify cleanup. Priority: P2 Review scores
Verification
How this fits togetherCodexBar runs Antigravity’s CLI to obtain usage data. The CLI can start configured MCP servers; the new cleanup runs after the usage command exits and before its temporary directory is removed. flowchart LR
A[Usage refresh] --> B[Antigravity CLI probe]
B --> C[Configured MCP servers]
B --> D[Process tracking]
C --> E[Temporary directory scan]
D --> F[Identity check and cleanup]
E --> F
F --> G[Usage result]
Before merge
Findings
Agent review detailsSecurityNeeds attention: The process tracker can signal descendants of an unrelated process if the probe PID is reassigned before polling ends. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Bind descendant polling to the probe’s PID and start identity, then show a redacted macOS refresh with before and after PID and parent-PID observations from configured MCP servers. Do we have a high-confidence way to reproduce the issue? No high-confidence current-main runtime reproduction was performed in this read-only review. Current source shows the missing successful-exit cleanup, and the PR body reports a macOS reproduction without a captured process listing. Is this the best way to solve the issue? The temporary-directory sweep and descendant tracking target the reported leak. The tracker also needs to verify the parent process identity before each scan, and the reported runtime result needs observable process evidence. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against cda264c299ad. LabelsLabel changes: No label changes. Label justifications:
EvidenceSecurity concerns:
What I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (1 earlier review cycle)
|
The directory sweep now stores each process start token and checks it again before SIGTERM and SIGKILL, so a reused PID is not signaled. SwiftFormat also wants the short usleep delay ungrouped and a normal comment on the runner flag.
Summary
CodexBar's Antigravity print-usage probe (
agy -p /usagein acodexbar-agy-usage-*temp directory) starts the user's configured MCP servers and then exits. Onagy1.2.2 and later the managed local-server path is skipped because of the CSRF token, so every refresh takes this print path.Servers launched with
npx/npm execcallsetsid. Whenagyexits they are reparented tolaunchd, stay in that temp directory, and each sit at about 100% CPU. The next refresh adds another set.SubprocessRunneronly reaps descendants on timeout or cancellation, and only while the parent is still alive, so a successful or already-exited probe leaves them running.This records descendant identities while the probe process is alive and signals any that are still running after it exits. It also kills whatever is left with that temp directory as its cwd before the directory is removed. Both signals re-check the process start token, so a PID reused during the wait is not killed. Both cases are covered by new
SubprocessRunnertests, including a child that calledstart_new_session.Test plan
swift test --filter 'reapDescendants kills|working directory reaper kills'agy1.2.2+ and severalnpxMCP servers configured, then confirm nonpm execprocesses remain parented tolaunchdRedacted macOS refresh (agy 1.2.12, MCP servers configured)
npm execprocesses immediately after, and again 2 seconds later, were the same set as before the command. Every one was parented to an already-running app. None were parented to launchd, and the refresh did not add any.