ACP bridge subprocesses are never reaped after an agent turn completes, leaking memory across all harnesses
- Dominant language
- Rust
- Stars
- 32.7k
- Forks
- 4.3k
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 253
Description
**Describe the bug**
When an agent (regardless of which ACP-compatible harness backs it) completes a turn and replies in a channel, the subprocess pool spawned to service that turn is not terminated or reaped. Each single message-to-agent interaction leaves behind roughly 10 idle child processes under the corresponding `buzz-acp` bridge, permanently, with no cleanup even minutes after the agent has finished responding and gone idle (confirmed via CPU dropping to ~0% and staying there).
This is harness-agnostic — reproduced identically with two different backing harnesses (a Claude-based agent and an opencode-based agent) in the same session. In each case, exactly one message produced exactly 10 leftover subprocesses that never exited.
Because this leak is per-message rather than per-session, it compounds continuously during normal use. Over roughly an hour of typical activity (multiple messages across multiple agents), leaked subprocess count reached ~88 processes consuming ~2.2GB RSS and ~2,100 open file descriptors. In a smaller two-message controlled test, 20 leaked processes alone accounted for ~3.78GB RSS and 627 open FDs — the two harnesses differ substantially in per-process footprint (~43MB/process for one harness's subprocesses vs. ~330MB/process for the other's), but both leak at the same ~10-processes-per-turn rate.
The resulting memory/FD pressure correlates with (and is the most likely cause of) several user-visible symptoms during sustained use:
- The relay WebSocket connection intermittently dropping, prompting a manual reconnect
- Sent/received messages failing to render in the UI
- Agents appearing unresponsive to new messages
**Steps to reproduce**
1. Launch Buzz desktop and note the baseline set of `buzz-acp` bridge child processes (e.g. `ps -eo pid,ppid,command | awk '$2=='`) — this is a stable pool with no further children yet.
2. Send a single message to any agent and wait for its reply to appear in the channel.
3. Inspect the children of that agent's `buzz-acp` bridge process (`pgrep -P `) — observe ~10 new subprocesses spawned.
4. Wait several minutes after the agent's reply is visible in the UI. Observe via `ps -o pid,%cpu,stat,etime` that these subprocesses drop to near-0% CPU (idle) but remain alive indefinitely — they are never terminated.
5. Repeat with a different backing harness for a different agent — same ~10-subprocess leak pattern occurs.
6. Repeat step 2 across multiple agents/messages over an extended session — leaked process count, RSS, and FD usage grow linearly and without bound.
**Expected behavior**
Once an agent turn completes and the reply has been delivered, all subprocesses spawned to service that turn should be terminated and reaped by their parent `buzz-acp` bridge. Steady-state process/memory/FD usage should return close to baseline between turns, regardless of which ACP harness backs the agent, and regardless of how many messages are sent over a session's lifetime.
**Version and platform**
- Buzz version: 0.5.3 (0.5.3)
- OS: macOS
**Logs / additional context**
Quantified from a controlled two-message test (one message per harness, one harness-A agent + one harness-B agent):
- 20 leaked subprocesses total (10 per harness), all confirmed idle (~0% CPU) for 10+ minutes after their agent's reply was posted
- ~3.78GB combined RSS across just these 20 processes
- 627 open file descriptors across just these 20 processes
- System-wide memory compressor usage rose to 9.6GB with under 1GB "unused" RAM remaining, from this test alone
From the original (uncontrolled) session that surfaced the symptom: ~88 leaked processes, ~2.2GB RSS, ~2,100 FDs, accumulated over roughly an hour of normal multi-agent usage, including at least one process that became a `` zombie never reaped by its parent. Fully quitting and relaunching the Buzz desktop app clears all leaked processes and temporarily resolves the disconnects/unresponsive-agent symptoms — until the leak reaccumulates with continued use.
---
Filed by Claude on behalf of the reporter.
Contributor guide
Research direction
Start by reproducing the leak in the Buzz desktop app and inspect the `buzz-acp` bridge process tree after an agent reply, using the listed `ps` and `pgrep` commands. Trace the subprocess pool lifecycle around turn completion and reply delivery. Done means turn-specific subprocesses are terminated and reaped for both Claude-based and opencode-based harnesses, with process, memory, and file-descriptor usage returning near baseline.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100