Skip to content

server: no SIGTERM handling, MCP stdio (docker) children orphaned on every stop/restart #50780

Closed as duplicate

Description

@sergio-asenjo

Summary

The v2 server never traps SIGTERM/SIGINT, so Effect scopes (including MCP stdio transports) are never closed on stop/restart/crash. Local docker run MCP servers orphan permanently — --rm doesn't save them since nothing ever stops the container. I accumulated ~95 orphaned postgres-mcp containers from normal restarts alone.

Environment

  • opencode version: v2.0.14
  • OS: Linux desktop 7.2.6-arch2-1 (x86_64, Arch)
  • Terminal: xterm-256color
  • Shell: /usr/bin/bash
  • Install/channel: latest (curl install, ~/.opencode/bin)

Reproduction

  1. Configure a local MCP server using docker run (e.g. crystaldba/postgres-mcp), open any project using it so the server connects.
  2. docker ps → one container running for the connection.
  3. Restart the server (opencode service restart, systemctl stop, or crash it).
  4. docker ps → the old container is still running; the new server generation spawns a fresh one. Repeat → unbounded pileup (I reached ~95).

Same leak via TUI flow, no restart involved:

  1. Attach a TUI to a running server (opencode --server http://localhost:4096), open a repo with a docker MCP.
  2. docker ps → container running.
  3. Ctrl+C the TUI (session stays server-side by design).
  4. The container keeps running indefinitely — observed persisting 20h+, well past the 60-minute location idle-eviction window, so eviction either never fires for these locations or doesn't tear down the MCP scope.

Expected Behavior

Server shutdown closes MCP scopes gracefully (the stdio transport already implements SIGTERM → 2s grace → SIGKILL in packages/core/src/mcp/stdio.ts), terminating child processes. Likewise, fully-idle locations (no attached clients, no active sessions) should release their MCP processes instead of holding them past the eviction window.

Actual Behavior

No signal handler exists anywhere in the server path (only desktop lifecycle, non-interactive runs, and profilers trap signals). Node dies instantly on SIGTERM; scopes/finalizers never run; docker children are adopted and run forever. Location idle eviction (60 min) only helps live servers, never post-restart orphans — and in the TUI-detach flow the containers outlive the eviction window.

Additional Context

  • Verified against v2 branch source (2026-09-22): packages/core/src/mcp/index.ts ("Connections remain Location-scoped"), packages/core/src/location-activity.ts (60-min TTL sweeper), packages/core/src/mcp/stdio.ts (graceful close that never gets invoked on shutdown).
  • Workaround: manually docker stop containers with no live docker run client process.
  • Related but distinct: Missing SIGHUP handler causes orphaned processes to leak ~4.7 GB each after terminal death #14504 (V1 TUI missing SIGHUP handler, closed).

Activity

  1. github-actions commented on Sep 23, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    In particular, #50758 appears to be nearly identical to this report. Please review it and let a maintainer know if your report covers a meaningfully distinct scenario (e.g. the SIGTERM signal handler gap specifically, or the docker --rm interaction) before we decide whether to consolidate.

  2. neriousy commented on Oct 20, 2026

    @neriousy
    Member

    Thanks for the report. We're tracking the same MCP child-process cleanup problem on service restart in #50758, so I'm closing this as a duplicate. Please follow that issue for updates.

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

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions