Skip to content

internal: Funnel all child process spawning through stdx::process - #22763

Open
Veykril wants to merge 3 commits into
rust-lang:masterfrom
Veykril:lukaswirth/push-qwnmnnpkpwxy
Open

internal: Funnel all child process spawning through stdx::process#22763
Veykril wants to merge 3 commits into
rust-lang:masterfrom
Veykril:lukaswirth/push-qwnmnnpkpwxy

Conversation

@Veykril

@Veykril Veykril commented Jul 11, 2026

Copy link
Copy Markdown
Member

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.

And enforce it via clippy. This allows us to easily manage process lifetimes and ensure tear down of child processes when r-a exits.
@Veykril
Veykril force-pushed the lukaswirth/push-qwnmnnpkpwxy branch from 43bd6b6 to f5168f8 Compare July 11, 2026 10:12
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.
@Veykril
Veykril force-pushed the lukaswirth/push-qwnmnnpkpwxy branch from f5168f8 to d12d79f Compare July 11, 2026 10:28
@Veykril
Veykril marked this pull request as ready for review July 11, 2026 10:29
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 11, 2026
@Veykril
Veykril requested a review from Copilot July 11, 2026 10:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) plus stdx::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.

View changes since this review

Comment thread crates/project-model/src/cargo_workspace.rs
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@Veykril
Veykril force-pushed the lukaswirth/push-qwnmnnpkpwxy branch from cf421d8 to 18a33ee Compare July 11, 2026 10:46
@ChayimFriedman2

Copy link
Copy Markdown
Contributor

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.

@Veykril

Veykril commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

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

@ChayimFriedman2

Copy link
Copy Markdown
Contributor

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 atexit() to kill this group on exit.

@Veykril

Veykril commented Jul 14, 2026

Copy link
Copy Markdown
Member Author

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)

@ChayimFriedman2

Copy link
Copy Markdown
Contributor

So, without diving deep into the code yet, I have two problems with the way this is implemented currently:

  1. This reimplements too much of the process API. We should only control spawning, and after that use standard stdlib APIs. In Windows, create a job in a static LazyLock, call creation_flags(CREATE_SUSPENDED) on the Command before spawning, spawn to get a Child, attach it to the job, then resume - resumption is a bit problematic because main_thread_handle() is currently unstable, so it seems the best way is to enumerate child threads and resume them. On Linux, use pre_exec() like you do; on other Unixes, use atexit() like I said above. We should still return JodChild to ensure termination on drop as well, but all APIs should just forward to std.
  2. I think that we should actually have our own JodCommand like in my PR; it both minimizes the risk for mistake as well as simplifies code that wants to spawn processes.

@rustbot

rustbot commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

☔ The latest upstream changes (possibly #22967) made this pull request unmergeable. Please resolve the merge conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants