[BUG] claude-vscode leaks one `dbus-daemon --session` per Bash tool call and per Task subagent on WSL2 (5620 orphans in 5 days)

Resolved 💬 1 comment Opened May 6, 2026 by raphaeldavidf Closed Jun 3, 2026

Summary

On WSL2, the Claude Code VSCode extension (CLAUDE_CODE_ENTRYPOINT=claude-vscode) leaks a dbus-daemon --session process every time a Bash tool call or Task (subagent) tool call is invoked. The daemon outlives the originating shell, gets reparented to WSL's /init (the WSL equivalent of PID 1), and accumulates indefinitely.

After ~5 days of normal use I had 5620 orphan dbus-daemon --session processes, all spawned in a Claude Code context, none with any child processes.

This is related to but distinct from #26987 (tab-close leaks): the rate (~46/hour) and the env evidence below show that per-tool-call shell creation is the primary driver, not tab opens. It also overlaps with #19045 / #20369 / #23154 / #33947 (subagent + MCP cleanup), but the leaked process here is an unrelated side-effect daemon (dbus-daemon), not the Claude/MCP child itself.

Environment

  • OS: Windows 11 + WSL2
  • Distro: Ubuntu (kernel 6.6.87.2-microsoft-standard-WSL2)
  • Shell: zsh
  • Claude Code via VSCode extension (Remote-WSL); CLAUDE_AGENT_SDK_VERSION=0.2.126
  • VSCode server build 10c8e557c8b9f9ed0a87f61f1c9a44bde731c409
  • No systemd in WSL (default)

Reproducer

  1. Use Claude Code via the VSCode extension on WSL2 normally for a few hours — invoke Bash tool calls and Task subagents as part of regular work.
  2. pgrep -af 'dbus-daemon.*--session' | wc -l — count grows monotonically.
  3. ps -eo pid,ppid,etime,cmd | awk '/[d]bus-daemon.*--session/ && $2 == 1' (substitute the PID of /init on WSL2; mine was 5104) — these are the orphans.

Evidence it's Claude Code

For each leaked daemon I dumped /proc/<pid>/environ. Counts:

| Env var | Count |
| --- | --- |
| CLAUDE_CODE_ENTRYPOINT=claude-vscode | 5620 / 5620 |
| CLAUDECODE=1 | 5619 / 5620 |
| CLAUDE_AGENT_SDK_VERSION=0.2.126 | 3132 / 5620 |

Reading:

  • 100% were forked in a claude-vscode context. No false positives from other tools.
  • ~56% carry the Agent SDK version env, so they came from Task (subagent) shells.
  • The remaining ~44% came from non-SDK contexts — main-agent Bash tool calls and the main interactive shell.

Other env vars present on every leaked daemon: VSCODE_IPC_HOOK_CLI, VSCODE_WSL_EXT_LOCATION, VSCODE_RECONNECTION_GRACE_TIME, VSCODE_HANDLES_SIGPIPE, OTEL_*, COPILOT_OTEL_*. So the leaked process inherits the full Claude-VSCode-WSL shell environment.

Age distribution (from ps etime, in days since start):

24    today
2533  1 day
736   2 days
76    3 days
1116  4 days
1134  5 days (since this WSL VM booted)

That's continuous accumulation, not a one-time burst. ~1100 leaked daemons/day = ~46/hour, which matches typical Bash + Task tool call rates during active use.

Mechanism (best guess)

  1. Claude Code spawns a fresh shell for each Bash tool call and each Task subagent.
  2. Something loaded into that shell's process tree calls into libdbus before DBUS_SESSION_BUS_ADDRESS is set. (The OTEL exporter and/or the VSCode IPC bridge are plausible candidates — note OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE and COPILOT_OTEL_EXPORTER_TYPE on every leaked daemon.)
  3. libdbus invokes dbus-launch --autolaunch, which double-forks a session bus. Signature on every leaked process: /usr/bin/dbus-daemon --syslog --fork --print-pid 5 --print-address 7 --session — exactly the autolaunch invocation.
  4. When the tool-call shell exits, Claude Code does not propagate SIGTERM to the daemon. The daemon was already detached by dbus-launch's double-fork, so it isn't a direct child anyway. WSL's /init adopts it.
  5. Multiplied by ~46/hour = thousands per day.

The two dbus-daemon --system processes on the box are unaffected; only --session leaks. The legitimate WSLg at-spi bus (started with explicit --address=unix:path=/mnt/wslg/runtime-dir/at-spi/bus_0) is unaffected — it has a live parent.

Workaround

Setting export DBUS_SESSION_BUS_ADDRESS=disabled: in ~/.zshrc / ~/.bashrc stops libdbus from autolaunching. For a typical headless dev workflow on WSL2 this has no observable impact (no notify-send, no libsecret, no systemctl --user).

Cleanup of existing orphans (safe — kills only daemons reparented to /init with no children):

INIT_PID=$(pgrep -of /init)  # WSL2 init pid
for pid in $(pgrep -f 'dbus-daemon.*--session'); do
  ppid=$(awk '{print $4}' /proc/$pid/stat 2>/dev/null)
  [ "$ppid" = "$INIT_PID" ] && [ -z "$(pgrep -P $pid)" ] && kill -TERM $pid
done

Suggested fix directions

  1. In the per-tool-call shell launcher, set DBUS_SESSION_BUS_ADDRESS=disabled: (or a project-scoped bus) in the child env unless the user has explicitly set it. Costs nothing for users who don't use dbus, doesn't interfere with users who do.
  2. Investigate whether the OTEL exporter / VSCode IPC native module is the actual libdbus consumer — if so, gate the dbus connection behind an availability check.
  3. Track tool-call-spawned shells and kill(SIGTERM, -pgid) the entire process group on completion, so any side-effect daemons die with the shell.

Related issues

  • #26987 (VS Code extension leaks Claude processes when closing tabs/panels — WSL2): same environment, different trigger; this issue is the per-tool-call analog.
  • #19045 (Task tool subagent processes not terminated after parent session ends — Linux): same lifecycle gap, different leaked process.
  • #20369 (Orphaned subagent process leaks memory when parent terminal session terminated)
  • #23154 (Subagents can't run TaskStop. Can orphan their own Bash tasks.) — overlaps with the Bash-tool half of this report.
  • #33947 (MCP server and subagent processes not cleaned up on session end — orphan accumulation, PPID=1)
  • #40667 (MCP server processes leak on host after subagent/session termination)

Why this matters

5620 idle dbus-daemon processes are ~3-5 MB RSS each = several GB of RAM held indefinitely, plus PID-table and FD-table pressure. On long-running WSL sessions this contributes meaningfully to the OOM patterns reported in #2938 and #18048.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗