[BUG] Grep tool hangs indefinitely with .{0,40}X.{0,40}-style regex (ugrep); orphaned child process survives shell termination

Open 💬 0 comments Opened Jul 13, 2026 by rrrrrrrrrricoxi

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

Claude Code's built-in Grep tool (backed by a bundled ugrep) can hang for many minutes — in our case, 20+ minutes before we manually killed it — on a tiny input when the regex has a bounded-repetition wildcard on both sides of the actual match, e.g. .{0,40}PATTERN.{0,40}. We isolated this to a minimal, fully reproducible case (below) using the standalone, published ugrep binary (v7.8.2 via Homebrew) — independent of Claude Code entirely — so the root cause appears to live in ugrep itself, not in Claude Code's integration.

Separately, we also observed that when the wrapping background shell is terminated, the underlying ugrep process is not terminated with it — it becomes an orphan (reparented to PID 1) and keeps consuming ~90-100% CPU indefinitely until manually kill -9'd.

What Should Happen?

Matching a single short line against a simple bounded-repetition pattern should complete near-instantly and scale roughly linearly with the bound size — not go from instant at N=20 to effectively hung at N=40.

Error Messages/Logs

Steps to Reproduce

brew install ugrep   # v7.8.2 at time of testing
printf 'Sample analysis indicates a positive trend across replicates for batch 1, ratio test X70 / Y30 concentration noted.' > mini.txt

# Hangs indefinitely (killed after 5s via timeout; CPU pinned ~95-100% the whole time):
timeout 5 ugrep -G -oE '.{0,40}X ?70.{0,40}' mini.txt   # exit 124, never produced output

# Near-instant with a slightly smaller bound, same input, same pattern shape:
timeout 5 ugrep -G -oE '.{0,20}X ?70.{0,20}' mini.txt   # completes in ~0.05s

We narrowed this down further; the hang does not depend on: alternation (single literal branch reproduces it just as reliably), -o (dropping it, plain -E, still hangs), -G vs -E (both hang identically), or CJK/multi-byte text (reproduces on pure ASCII).

It does depend on the bound size on both sides simultaneously: on the exact same one-line input, .{0,20}...{0,20} completes in ~50ms, while .{0,40}...{0,40} never completes. We didn't bisect the exact transition point, but 20 vs 40 alone is already a >100x slowdown — consistent with an exhaustive search over both bounded quantifiers (e.g. for POSIX leftmost-longest matching) rather than an early-exit/anchored search.

This is a single ~120-byte, single-line input — no large file or corpus is needed to trigger a hang that scales from milliseconds to (in our real-world case) tens of minutes.

Claude Model

Sonnet (default)

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.207

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

Ghostty terminal emulator

Secondary issue: orphaned child process on shell termination

When we sent SIGTERM to the background shell running the stuck search, the shell exited, but its ugrep child was not terminated with it — it was reparented to PID 1 and kept running until manually SIGKILL'd. Practical impact: stopping a runaway search by killing the wrapping shell/task doesn't actually free the CPU.

Suggested next steps

  • The regex-performance issue looks upstream in ugrep itself — may be worth relaying to github.com/Genivia/ugrep too, if not already known there.
  • Regardless, it'd help for Claude Code's Grep tool to enforce a subprocess timeout, and ensure child processes are actually terminated when the wrapping shell/task is stopped.

View original on GitHub ↗