Skip to content

MCP server process doesn't exit after idle timeout (blocked on stdin.read) #245

@justrach

Description

@justrach

Problem

The MCP server watchdog correctly detects idle timeout and attempts to close stdin to wake up the main thread, but the process doesn't actually exit because the main thread is blocked on a blocking readLine() call.

Current Behavior

  1. idleWatchdog thread detects idle timeout after 10 minutes (or custom timeout via --timeout)
  2. Watchdog calls stdin.close() and sets shutdown = true
  3. Main thread is blocked in mcpj.readLine() waiting for input
  4. Process remains running indefinitely

This was reported by @destroyer22719 in #243 - they observed the MCP process still running even after the timeout period.

Root Cause

The main MCP loop (src/mcp.zig:427-428):

while (true) {
    const msg = mcpj.readLine(alloc, stdin) orelse break;

Uses blocking I/O. When stdin.close() is called from the watchdog thread, the blocking read doesn't get interrupted on all platforms/pipe configurations.

Potential Solutions

  1. Non-blocking reads with timeout: Use poll() before reading to check if data is available, with a timeout that lets us periodically check the shutdown flag

  2. Signal-based interruption: Have the watchdog send a signal (SIGUSR1) to the main thread to interrupt the read

  3. Thread cancellation: More drastic - cancel the main thread from the watchdog (complex and risky)

  4. Process self-termination: Instead of waiting for the main thread to exit, the watchdog could call std.process.exit() directly after logging the idle timeout

Workaround

Users can currently work around this by:

  • Using pkill codedb or similar to force kill the process
  • Setting a longer timeout with --timeout=N to reduce how often this happens

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    status:backlogWork item has not been started

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions