Skip to content

Memory Leak: Orphaned processes when terminal closes without explicit exit #10563

Closed

Description

@Her-xanadu

Problem

When users close terminal windows without explicitly exiting OpenCode (Ctrl+C), the OpenCode process and all its MCP child processes become orphaned (parent becomes launchd/PID 1) and continue consuming memory indefinitely.

Evidence from a real user system:

=== OpenCode Process Stats ===
      41 OpenCode processes
OpenCode main processes: 2638 MB
MCP child processes: 404 MB
Total: ~3.0 GB wasted memory

=== By TTY ===
  38 ??    # Orphaned processes (no controlling terminal)
   3 active terminals

All 38 orphaned processes had PPID=1 (adopted by launchd), meaning their original terminal was closed but the process didn't exit.

Root Cause

OpenCode doesn't properly handle terminal closure signals (SIGHUP) or doesn't propagate termination to MCP child processes.

Proposed Solution

Option 1: Fix in OpenCode Core (Recommended)

Add proper signal handling in the main process:

// Example for Go codebase
func setupSignalHandling() {
    sigs := make(chan os.Signal, 1)
    signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
    
    go func() {
        <-sigs
        // Kill all child processes (MCP servers)
        killChildProcesses()
        os.Exit(0)
    }()
}

func killChildProcesses() {
    // Get process group and kill all children
    pgid, err := syscall.Getpgid(os.Getpid())
    if err == nil {
        syscall.Kill(-pgid, syscall.SIGTERM)
        time.Sleep(500 * time.Millisecond)
        syscall.Kill(-pgid, syscall.SIGKILL)
    }
}

Option 2: Wrapper Script Workaround (User-side)

For users experiencing this issue now, a wrapper script can help:

#!/bin/bash
# ~/.local/bin/opencode-wrapper

OPENCODE_BIN="/opt/homebrew/bin/opencode"  # or wherever opencode is installed

cleanup() {
    get_descendants() {
        local parent=$1
        local children=$(pgrep -P $parent 2>/dev/null)
        for child in $children; do
            echo $child
            get_descendants $child
        done
    }
    
    local all_children=$(get_descendants $$)
    
    if [ -n "$all_children" ]; then
        echo $all_children | xargs kill 2>/dev/null
        sleep 0.5
        echo $all_children | xargs kill -9 2>/dev/null
    fi
}

trap cleanup EXIT INT TERM HUP QUIT
exec "$OPENCODE_BIN" "$@"

Installation:

chmod +x ~/.local/bin/opencode-wrapper
echo 'alias opencode="~/.local/bin/opencode-wrapper"' >> ~/.zshrc
source ~/.zshrc

Expected Behavior

  1. When terminal is closed (SIGHUP), OpenCode should terminate gracefully
  2. All MCP child processes should be killed before OpenCode exits
  3. No orphaned processes should remain after terminal closure

Environment

  • macOS (arm64)
  • OpenCode installed via Homebrew
  • Multiple MCP servers configured (ssh-mcp, figma, arxiv, markitdown, chrome-devtools, github)

Impact

  • Memory leak: Each orphaned instance uses 60-90 MB
  • MCP processes: Additional ~10 MB per MCP per instance
  • After a week of usage without manual cleanup: 2-3 GB wasted memory

Activity

  1. added
    perfIndicates a performance issue or need for optimization
    on Jan 25, 2026
  2. github-actions commented on Jan 25, 2026

    @github-actions
    Contributor

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

    Feel free to ignore if none of these address your specific case.

  3. TomasHubelbauer commented on Jan 31, 2026

    @TomasHubelbauer

    I am experiencing the same even with no MCP servers: #11527. Looks like a general issue with how OpenCode handles its sub-processes, though I am left wondering why with no plugins nor any MCP servers my OpenCode instance still spawns a sub-process.

  4. dollannn commented on Feb 9, 2026

    @dollannn

    Big issue for me - consuming 28GB of memory

  5. kavhnr commented on Feb 19, 2026

    @kavhnr
    Contributor

    Had the same issue, our team built a lightweight opencode wrapper that does session-scoped process cleanup (so closing one window/session won’t affect another) and cleans leftovers on exit/interrupt. Shared it here for easy use while upstream fixes land: https://github.com/kavhnr/oclean

  6. OmerFarukOruc commented on Feb 27, 2026

    @OmerFarukOruc

    If you're hitting this on Linux — I wrote a cleanup script that finds and kills orphaned opencode processes (no TTY). Quick workaround until it's fixed.

    curl -fsSL https://gist.githubusercontent.com/OmerFarukOruc/d1bf2bb1f6f4f01c3a0e63288ada7c94/raw/oc-cleanup -o ~/.local/bin/oc-cleanup && chmod +x ~/.local/bin/oc-cleanup

    Usage: oc-cleanup (list), oc-cleanup kill (kill orphans), oc-cleanup watch (monitor all)

    Full gist + README: https://gist.github.com/OmerFarukOruc/d1bf2bb1f6f4f01c3a0e63288ada7c94
    See also: #15348

  7. thdxr commented on Apr 2, 2026

    @thdxr
    Member

    Closing in favor of #20695 where we're collecting all memory-related problems. 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

perfIndicates a performance issue or need for optimization

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions