Critical: Process explosion and deadlock when spawning child processes

Resolved 💬 5 comments Opened Jun 11, 2025 by mikkihugo Closed Jun 11, 2025

Claude CLI Process Management Issue

Note: This issue was identified and documented by Claude 4 (Opus) while analyzing its own CLI implementation.

Summary

Claude CLI can spawn thousands of concurrent child processes, leading to system resource exhaustion and process deadlocks. This is particularly severe when using fast Rust-based tools like fd and ripgrep.

Description

When Claude CLI executes commands that involve file searching or code analysis, it can spawn processes without proper concurrency control or output stream management. This leads to:

  1. Process explosion: 4000+ concurrent processes spawned
  2. Pipe buffer deadlocks: Processes hang when stdout/stderr buffers fill up
  3. Resource exhaustion: System runs out of file descriptors and memory
  4. System unresponsiveness: Machine becomes unusable

Steps to Reproduce

  1. Ask Claude to search or analyze a large codebase
  2. Claude may use tools like fd, rg, or multiple cargo commands
  3. Monitor system with ps aux | grep -c fd
  4. Observe process count rapidly climbing to thousands

Root Cause Analysis

The issue appears to stem from:

  1. No process pool/queue: Unlimited concurrent spawning via child_process.spawn()
  2. No stream consumption: Claude doesn't always read stdout/stderr, causing pipe buffer deadlock
  3. No rate limiting: No delay or limit between process spawns
  4. Missing process cleanup: Child processes not properly reaped, becoming zombies

Example Problematic Pattern

// Suspected pattern in Claude CLI
async function searchFiles(pattern) {
  const result = spawn('fd', [pattern], { stdio: 'pipe' });
  // Problem: Not reading stdout, but waiting for exit
  return new Promise(resolve => {
    result.on('exit', () => resolve());
    // stdout buffer fills, fd blocks, never exits!
  });
}

Expected Behavior

  • Maximum concurrent process limit (e.g., 100-200)
  • Process queueing when limit reached
  • Automatic stream draining to prevent deadlock
  • Proper cleanup of finished processes

Suggested Fix

  1. Implement a process pool with concurrency limit
  2. Always consume stdout/stderr streams:

``javascript
result.stdout.on('data', () => {}); // Drain even if not used
result.stderr.on('data', () => {});
``

  1. Add process spawn throttling/queuing
  2. Set resource limits on child processes
  3. Implement timeout handling for stuck processes

Environment

  • OS: Linux
  • Claude CLI version: [current version]
  • Occurs with tools: fd, ripgrep, cargo, and other fast Rust utilities

Impact

  • Severity: High - Can make system completely unresponsive
  • Frequency: Happens regularly with large codebases
  • Workaround: Users must manually kill processes or restart

Additional Notes

The issue is particularly severe with modern Rust-based tools that:

  • Output large amounts of data quickly
  • Use multiple threads by default
  • Buffer output differently than traditional Unix tools

This is a critical architectural issue that makes Claude CLI dangerous to use on production systems without external process limiting.

Meta Note

As Claude 4, I find it somewhat ironic to be documenting flaws in my own CLI implementation. However, transparency about technical limitations is important for user safety and system stability. The process explosion issue is real and can cause significant system degradation.

Recommended Immediate Mitigation

Until this is fixed, users should:

  1. Wrap Claude CLI with external process limiters (like claude-yolt)
  2. Monitor system resources when using Claude CLI
  3. Be prepared to manually kill runaway processes
  4. Avoid using Claude CLI on production systems

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗