Skip to content

fix: exit process when ACP connection closes#530

Open
WayChan wants to merge 1 commit intoagentclientprotocol:mainfrom
WayChan:fix/exit-on-connection-close
Open

fix: exit process when ACP connection closes#530
WayChan wants to merge 1 commit intoagentclientprotocol:mainfrom
WayChan:fix/exit-on-connection-close

Conversation

@WayChan
Copy link
Copy Markdown

@WayChan WayChan commented Apr 8, 2026

Summary

  • Return AgentSideConnection from runAcp() instead of discarding it
  • Listen for connection.closed and call process.exit(0) on resolution
  • Fixes orphan process accumulation in oneshot mode (e.g. via ACPX)

Problem

When used in oneshot mode, claude-agent-acp does not exit after the client closes the stdin pipe. process.stdin.resume() keeps the Node.js event loop alive indefinitely. Over time, orphan processes accumulate on the host (~97MB RSS each), eventually exhausting system resources.

Root cause

runAcp() creates an AgentSideConnection but discards the reference. The Connection.#receive() loop detects stdin EOF and fires abortController.abort(), resolving connection.closed — but no code listens for it to trigger process.exit().

Fix

  1. acp-agent.ts: runAcp() now returns the AgentSideConnection instance
  2. index.ts: Awaits connection.closed and calls process.exit(0)

Impact

  • Oneshot sessions: Process now exits cleanly when the client closes stdin (EOF)
  • Persistent sessions: Unaffected — the client keeps stdin open, so connection.closed does not fire until explicit disconnect

Test plan

  • Verified oneshot: process exits within 1s after stdin EOF
  • Verified persistent: process remains alive while stdin is open
  • Measured idle RSS: ~97MB → freed on exit
  • Tested with ACPX runtime (OpenClaw gateway) in production

🤖 Generated with Claude Code

In oneshot mode (e.g. via ACPX), the claude-agent-acp process does not
exit after the client closes the stdin pipe. `process.stdin.resume()`
keeps the Node.js event loop alive indefinitely, causing orphan process
accumulation on the host.

Root cause: `runAcp()` discards the `AgentSideConnection` instance, so
nothing listens for connection closure to trigger `process.exit()`.

Fix: return the connection from `runAcp()` and call `process.exit(0)`
when `connection.closed` resolves (i.e. when stdin reaches EOF).

Persistent sessions are unaffected — the client keeps stdin open, so
`connection.closed` does not fire until the client explicitly
disconnects.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@WayChan WayChan closed this Apr 8, 2026
@WayChan WayChan reopened this Apr 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants