fix(rust): prevent orphaned CLI processes - #2292
Conversation
Bind each spawned CLI transport to an SDK-owned process tree before it can create descendants. Use a kill-on-close Job Object on Windows and a process group on Unix, and carry the RAII owner through startup, stop, force-stop, and drop paths. Cover grandchild teardown and startup-failure cleanup without changing the public client API. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1090dd5b-e149-4d9d-9cc3-67f26e11ad06
There was a problem hiding this comment.
Pull request overview
Adds cross-platform process-tree ownership and teardown for Rust SDK-spawned CLI processes.
Changes:
- Uses Unix process groups and Windows Job Objects.
- Integrates tree termination into startup, stop, force-stop, and drop paths.
- Adds lifecycle and process-tree tests.
Show a summary per file
| File | Description |
|---|---|
rust/src/process_tree.rs |
Implements process-tree lifecycle management. |
rust/src/lib.rs |
Integrates managed children into the client lifecycle. |
rust/src/errors.rs |
Updates teardown error documentation. |
rust/Cargo.toml |
Adds platform-specific dependencies. |
rust/Cargo.lock |
Locks the added dependencies. |
Review details
- Files reviewed: 4/5 changed files
- Comments generated: 3
- Review effort level: Balanced
Match the repository's nightly rustfmt configuration on Linux. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1090dd5b-e149-4d9d-9cc3-67f26e11ad06
|
Spent time on this against github/app#2303. I think the fix is already in this diff — it's just not the headline change.
Could we land this PR as just those two changes plus their tests? That fixes #2303 on its own. On the process-tree work — I don't think it's wrong, but it's solving a different failure mode and I'd like to separate it. The issue reports "61 orphaned hosts with zero descendants," so descendant containment isn't what's broken here. The genuinely unique thing it buys is Windows
A few things worth carrying into that PR whenever it happens: the reaper thread in Last thing, and I think it's the highest-leverage one: should the runtime just exit on its own? The logs show Generated by Copilot |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Generated by Copilot Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Summary
ClientInnerand its CLI child alive after the lastClientwas droppedkill_on_dropfor SDK-spawned CLI commands so startup failures cannot strand a child before ownership reachesClientInnerFixes github/app#2303.
Validation
dropping_last_client_kills_spawned_clifails against the original lifecycle cycle withchild survived after its owner was dropped, then passes with the fixcargo test --no-default-features --lib dropping_last_client_kills_spawned_clicargo test --no-default-features --lib spawned_child_is_killed_when_droppedGenerated by Copilot