Skip to content

[Bug] Hook subprocess cleanup causes 100% CPU freeze on task interruption #55609

Closed as not planned

Description

@boshu2

Bug Description

Refining the repro for the long-running 100% CPU freeze in 2.1.x (cross-ref public issues #27415 and #18532).

I now think this is hook-related, not just TaskStop-related.

Repro (4 steps, ~60 sec):

  1. Have any hook configured in ~/.claude/settings.json (SessionStart / SessionEnd / Stop / PreToolUse / PostToolUse — especially ones running shell scripts)
  2. Start a Claude session
  3. Run any backgrounded bash tool
  4. Interrupt — Ctrl-C, ask Claude to kill the task, or close the tab while the tool is mid-flight

100% CPU spin every time, force-kill required. Vanilla claude installs with no hooks seem much less likely to trigger.

5-minute test for the hypothesis (anyone on your team can run this):

mv ~/.claude/settings.json ~/.claude/settings.backup.json
echo '{}' > ~/.claude/settings.json
claude
# (run + interrupt a backgrounded task)
mv ~/.claude/settings.backup.json ~/.claude/settings.json

If freeze stops with vanilla settings and reproduces with hooks, root cause is in the hook-subprocess + interrupt cleanup path. That would also explain why engineers on stock dev boxes don't reproduce on the first try, while users with AgentOps / custom MCP / status-line wrappers hit it daily.

I have a fresh forensic capture from 2026-05-02: independent 1Hz monitor logged the entire userland stalling for 24 seconds during the freeze. macOS 26.4.1 / M5 / 32 GB / claude 2.1.126. Happy to share.

Environment Info

  • Platform: darwin
  • Terminal: ghostty
  • Version: 2.1.126
  • Feedback ID: 53400c39-c176-4667-83ae-be548fa1e5d6

Note on auto-attached errors: the in-app /bug flow auto-attached two prompt is too long: 1006407 tokens > 1000000 maximum errors. Those are unrelated to this bug — they're context-overflow errors from a long-running session in this same window. They're not part of the freeze repro. Stripped from this issue body to avoid confusing the diagnosis.

Disclosure: I build AgentOps on top of Claude Code; filing as a daily user.

Activity

  1. github-actions commented on May 2, 2026

    @github-actions

    Found 3 possible duplicate issues:

    1. [BUG] 100% CPU freeze on TaskStop — runaway posix_spawn loop in Bun runtime #27415
    2. [BUG] tree-kill dependency causes pgrep storm / 100% CPU when reaping Bash subprocess trees on macOS #52253
    3. v2.1.23+ causes 100% CPU hang with multiple parallel instances and hooks #22172

    This issue will be automatically closed as a duplicate in 3 days.

    • If your issue is a duplicate, please close it and 👍 the existing issue instead
    • To prevent auto-closure, add a comment or 👎 this comment

    🤖 Generated with Claude Code

  2. boshu2 commented on May 2, 2026

    @boshu2
    Author

    Quick add — quantitative scope, in case "happens multiple times a day" reads as anecdotal.

    While diagnosing this morning I had a freeze-capture monitor running. Between 08:32 and 12:05 PDT today (~3.5 hours of active dev work), the monitor caught 21 distinct freeze events across 5 separate claude PIDs (28428, 42495, 47974, 55383, 99538). It's not a flaky thing that happens daily — it's a freeze every ~10 minutes when actively using claude with hooks configured.

    System-load evidence:

    • Baseline 1-min load average (idle Mac): 3.37
    • During freeze peaks: l1=18.99, l1=18.51, l1=13.58 (5.6× baseline)
    • Threshold for "system stalled" trips: load > 6.74

    Process-starvation evidence (the strongest single piece): the freeze-capture monitor itself hit fork: retry: Resource temporarily unavailable repeatedly while trying to spawn sample/vm_stat to capture state. That's macOS refusing to allocate new process slots. Not just claude was stuck — the kernel was rejecting fork() system-wide. The monitor's own bash interpreter was waiting on retry loops.

    Sample of one stuck claude (PID 77747, taken 2026-05-02 08:27:44, claude 2.1.126, macOS 26.4.1):

    • 2,561 thread samples on main thread (com.apple.main-thread, serial)
    • All 2,561 in the same call path: + 0x6569a0 → 0xe37c6c → 0x849910 → ...
    • Same syscall-loop signature as @smconner's Linux x86_64 gcore disassembly upthread

    I have the full forensic dir — 7 freeze snapshots, the 21-event log, sample profiles for 5 PIDs, vm_stat captures, top.log, fork-failure stdout — happy to share with whoever picks this up.

  3. boshu2 commented on May 2, 2026

    @boshu2
    Author

    Caught the parent PID red-handed in a system spindump while reproducing the 4-step repro from this issue body. macOS 26.4.1 / M5 / 32 GB / 2.1.126 / Ghostty.

    Main thread 1000/1000 samples in __posix_spawn → __socketpair → setsockopt → __close_nocancel. Kernel turnstile waits name pgrep and spindump children. Footprint +1577 MB in 10s. kill -9 to recover.

    Full forensic write-up and root-cause discussion: #52253 (comment). The repro in this issue body is the userland trigger for that bug.

  4. IgorGanapolsky commented on May 28, 2026

    @IgorGanapolsky

    External mitigation note while the root cause inside Claude Code is being narrowed:

    The class of failure here — agent CLI leaves child processes spinning until force-kill — is catchable at the OS layer. On 2026-05-26 I hit a related pattern (load avg spiked to 307 from un-reaped iOS simulator children, also M5 / macOS 26.5 / Ghostty) and ended up writing a small LaunchAgent + wrapper combo to keep it from happening again. Open-sourced as https://github.com/IgorGanapolsky/mac-yolo-safeguards.

    For the hook-cleanup-on-interrupt pattern @boshu2 reproduces specifically: the wrapper's stuck-loop watchdog kills the parent if it stays above 80% CPU for 2 minutes straight, catching the spinning state before manual force-kill is needed. The LaunchAgent only shuts down simulators — never touches GUI apps (no chance of losing unsaved IDE work). MIT, zero telemetry, install/uninstall is 4 symlinks.

    Doesn't fix the root cause and is no substitute for a fix inside Claude Code, but takes the freeze out of the recovery loop while this gets diagnosed.

  5. boshu2 commented on May 28, 2026

    @boshu2
    Author

    @IgorGanapolsky thank you! will try it out tonight. Crazy this still has yet to be fixed

  6. github-actions commented on Jun 30, 2026

    @github-actions

    Closing for now — inactive for too long. Please open a new issue if this is still relevant.

  7. github-actions commented on Sep 2, 2026

    @github-actions

    This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.

  8. locked as resolved and limited conversation to collaborators on Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions