Hook timeout does not reclaim a hook blocked in a read syscall — SIGTERM ignored, process survives indefinitely

Status Closed — not planned
Maintainer reply None cached
Activity 2 comments · opened Aug 14, 2026 · closed Aug 16, 2026

Summary

A hook that blocks on a read syscall is not reclaimed by its configured timeout. The timeout fires, SIGTERM is delivered, and the process keeps running. Only SIGKILL or SIGQUIT ends it.

Measurement

A Go binary invoked as a hook called io.ReadAll(os.Stdin) unconditionally. When stdin was a FIFO that never reached EOF:

  • timeout 8 <hook> → process still alive at 383 seconds
  • timeout 10 <hook> → process still alive at 200 seconds
  • In both cases timeout itself sat in sigsuspend, waiting on a child that would not die
  • With stdin closed, the same binary returned rc=0 in 49 ms

Goroutine dump of the blocked process (GOTRACEBACK=all):

goroutine 1 gp=0xc000002380 m=4 mp=0xc000075808 [syscall]:
syscall.Syscall(0x0, 0x0, 0xc0000a8000, 0x200)
...
io.ReadAll({0xc1f8c0, 0xc00011e028})

Goroutine 1 is parked in the blocking read on a locked thread, so the Go runtime never reaches its signal handler. Any process whose main thread blocks in an uninterruptible-ish syscall will behave the same way; this is not Go-specific in principle.

Why it matters

The timeout field on a hook is the sanctioned mitigation for a misbehaving hook, and it does not work against the failure mode that most needs it — a hook wedged on I/O rather than spinning. For a UserPromptSubmit hook this stalls every prompt in the session, and a wedged hook prints nothing, so the broken state is indistinguishable on stdout from the healthy "nothing to report" state.

Suggested fix

Escalate on timeout: SIGTERM, wait a short grace period, then SIGKILL. Optionally surface a one-line notice when the escalation is used, so a hook that had to be killed is visible rather than silent.

Environment

  • Platform: Linux 6.8.0-136-generic
  • Hook types observed: UserPromptSubmit, PreToolUse
  • Reproduces with a command hook whose stdin is an open FIFO with no writer sending EOF

Related

#78756 reports hooks hanging because the client never closes the hook's stdin pipe (Windows). That is a cause; this issue is about the mitigation — a hook wedged that way cannot be reclaimed by its timeout, whatever wedged it.

View original on GitHub ↗

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