mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
Two bugs caused MCP server child processes (e.g. `npm`/`node` for `mcp-remote`) to accumulate as zombie processes that were never cleaned up: **Bug 1: `stop_server()` only called `stop()` for `Running` servers** If a server completed initialization but was still in `Starting` state when `stop_server()` was called (a race between the init task completing and `maintain_servers` restarting), the client/transport/process were never released. The `Arc<ContextServer>` was moved into a `Stopped` state with its inner client still holding the transport and child process handle. Fix: call `stop()` unconditionally in `stop_server()`. It is a safe no-op when the client has not been initialized (`None`). **Bug 2: `kill_on_drop` only killed the direct child, not the process tree** `StdioTransport` used a raw `smol::process::Child` with `kill_on_drop(true)`, which sends SIGKILL only to the direct child process (the shell/`npm` wrapper). The actual MCP server (e.g. `node mcp-remote`) runs as a grandchild and survives the kill, getting reparented to launchd. Fix: use `util::process::Child`, which already exists in the codebase for exactly this purpose. It calls `setsid()` via `pre_exec` to make the child a process group leader, and uses `killpg()` to terminate the entire process tree on kill. This requires passing a `std::process::Command` (via `build_std_command`) instead of a `smol::process::Command` (via `build_smol_command`), because that is what `util::process::Child::spawn` accepts — it needs to call `pre_exec` on the `std::process::Command` before internally converting it to `smol::process::Command` for async I/O. Release Notes: - Fixed zombie MCP server processes accumulating over time
45 lines
1 KiB
TOML
45 lines
1 KiB
TOML
[package]
|
|
name = "context_server"
|
|
version = "0.1.0"
|
|
edition.workspace = true
|
|
publish.workspace = true
|
|
license = "GPL-3.0-or-later"
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[lib]
|
|
path = "src/context_server.rs"
|
|
|
|
[features]
|
|
test-support = ["gpui/test-support"]
|
|
|
|
[dependencies]
|
|
anyhow.workspace = true
|
|
async-channel.workspace = true
|
|
async-trait.workspace = true
|
|
base64.workspace = true
|
|
collections.workspace = true
|
|
futures.workspace = true
|
|
futures-lite.workspace = true
|
|
gpui.workspace = true
|
|
http_client = { workspace = true, features = ["test-support"] }
|
|
log.workspace = true
|
|
net.workspace = true
|
|
parking_lot.workspace = true
|
|
rand.workspace = true
|
|
postage.workspace = true
|
|
schemars.workspace = true
|
|
serde_json.workspace = true
|
|
serde.workspace = true
|
|
settings.workspace = true
|
|
sha2.workspace = true
|
|
slotmap.workspace = true
|
|
tempfile.workspace = true
|
|
tiny_http.workspace = true
|
|
url = { workspace = true, features = ["serde"] }
|
|
util.workspace = true
|
|
|
|
[dev-dependencies]
|
|
gpui = { workspace = true, features = ["test-support"] }
|
|
pollster.workspace = true
|