internal: Funnel all child process spawning through stdx::process - #22763
internal: Funnel all child process spawning through stdx::process#22763Veykril wants to merge 3 commits into
Conversation
And enforce it via clippy. This allows us to easily manage process lifetimes and ensure tear down of child processes when r-a exits.
43bd6b6 to
f5168f8
Compare
Tie child process lifetimes to rust-analyzer's own via kernel primitives, covering exits that never run cleanup code (crashes, hard kills): * windows: assign the rust-analyzer process itself to a job object with JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE at startup. All descendants (including e.g. rustc spawned by cargo) inherit job membership, and the kernel kills every remaining member when the deliberately leaked job handle is closed on process death. * linux: set PR_SET_PDEATHSIG=SIGKILL in a pre_exec hook at the spawn chokepoint, with a getppid check to close the race where the parent dies before the prctl. This covers direct children only; process groups from spawn_grouped handle grandchildren on the graceful path. * macos: no equivalent kernel primitive exists; children are only cleaned up on graceful exit. AI usage disclosure: implemented with an AI agent (Claude Fable 5 in Zed), driven and reviewed by a human.
f5168f8 to
d12d79f
Compare
There was a problem hiding this comment.
Pull request overview
This PR centralizes child-process spawning behind stdx::process and enforces the rule via Clippy, enabling consistent process lifetime management and better cleanup of spawned processes when rust-analyzer exits (especially on Windows/Linux).
Changes:
- Introduces
stdx::process::JodChild(direct + grouped spawning) plusstdx::process::output, and wires rust-analyzer call sites through these chokepoints. - Adds
stdx::process::kill_descendants_on_exit()and invokes it early in the rust-analyzer binary to enable OS-level descendant cleanup on Windows. - Updates Clippy configuration to disallow
std::process::Command::{spawn,output,status}and adjusts affected code paths (plus targeted allowances for examples).
Reviewed changes
Copilot reviewed 18 out of 19 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| lib/lsp-server/examples/minimal_lsp.rs | Adds a targeted Clippy allowance for example-only direct Command::spawn usage. |
| crates/stdx/src/process.rs | Expands process utilities: introduces JodChild, spawn chokepoints, Windows job setup, and output helpers. |
| crates/stdx/src/lib.rs | Removes the old stdx::JodChild and gates stdx::process behind cfg(not(wasm32)). |
| crates/stdx/Cargo.toml | Adds process-wrap dependency for non-wasm targets; expands windows-sys feature set. |
| crates/rust-analyzer/tests/slow-tests/main.rs | Switches rustfmt probing to stdx::process::output. |
| crates/rust-analyzer/src/handlers/request.rs | Routes rustfmt spawning through stdx::process::JodChild::spawn. |
| crates/rust-analyzer/src/config.rs | Normalizes CRLF/LF in a test input to make marker searching robust across checkouts. |
| crates/rust-analyzer/src/command.rs | Replaces local grouped-child handling with stdx::process::JodChild and grouped spawning. |
| crates/rust-analyzer/src/bin/rustc_wrapper.rs | Uses JodChild::spawn for rustc wrapper process creation and waiting. |
| crates/rust-analyzer/src/bin/main.rs | Calls stdx::process::kill_descendants_on_exit() early in startup. |
| crates/rust-analyzer/Cargo.toml | Drops direct process-wrap dependency (now provided via stdx). |
| crates/project-model/src/sysroot.rs | Switches tool output capturing to stdx::process::output. |
| crates/project-model/src/lib.rs | Switches Command::output usage to stdx::process::output. |
| crates/project-model/src/cargo_workspace.rs | Replaces cargo_metadata execution path with a helper that uses stdx::process::output. |
| crates/proc-macro-api/src/process.rs | Moves proc-macro server spawning to stdx::process::JodChild and updates stdio access. |
| crates/ide/src/syntax_highlighting/tests.rs | Simplifies expect_file! invocation (removes unnecessary format!). |
| crates/ide/src/expand_macro.rs | Routes rustfmt spawning through stdx::process::JodChild::spawn and updates stdin access. |
| clippy.toml | Disallows Command::{spawn,output,status} to enforce the new chokepoint APIs. |
| Cargo.lock | Reflects dependency graph updates (moves process-wrap usage under stdx). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
cf421d8 to
18a33ee
Compare
|
This does seem like a better way 😢 (sad because I've spent quite a lot of time on solving and debugging that PR), but I have some notes on the implementation. |
|
Did you mean to send those notes as a review that you didn't submit by accident? Or are those still coming? Not too sure how happy I am with the current impl here either |
|
I didn't send them or reviewed the code thoroughly yet; one comment, however, is that it seems to be possible to also do this on macOS (or any Unix), by associating the child processes with a process group then using |
|
Ah yea no worries then if you just haven't found the time yet, just sounded like you might not have sent the review by accident (has happened to me before) |
|
So, without diving deep into the code yet, I have two problems with the way this is implemented currently:
|
|
☔ The latest upstream changes (possibly #22967) made this pull request unmergeable. Please resolve the merge conflicts. |
And enforce it via clippy. This allows us to easily manage process lifetimes and ensure tear down of child processes when r-a exits.
Alternative to #22738, note this does nothing for macos though, as macos seems to lack a nice way of doing this.