Skip to content

loopdriver: starvation-halt path can hang forever on a child's unclosed stdout (os/exec io.Copy) #286

Description

@linhdmn

Observed 2026-09-10 on the live loop (PID 84739, devagent-go @ main pre-00:03 build):

Symptom. The driver printed [starvation] 15 consecutive non-productive iterations — halting loop at 08:00 local and then never exited. sample showed: no children, no sockets, STAT R→cond-wait, 6.8 MB RSS, main thread in pthread_cond_wait. SIGQUIT goroutine dump (captured in hub selfbuild-loop-v21 logs) shows the culprit:

goroutine 23 [IO wait]:
os/exec.(*Cmd).Start.gowrap1() → os/exec writerDescriptor.func1
io.copyBuffer(os.File stdin/stdout pipe → io.Writer)

Root cause. A child process spawned during the iteration (pane-run/exec helper) kept its stdout pipe open after the driver's starvation gate decided to halt. cmd.Wait() (or the post-Start copy-teardown on the return path) blocks forever in io.Copy reading that pipe — the halt return 0 at internal/loopdriver/run.go:128-131 never completes. The process becomes an unkillable-looking zombie driver: alive, holding the repo cwd, but dispatching nothing. The TUI then reads the daemon's /status as idle-with-no-queue forever.

Fix direction. Bound the teardown on the halt path: after the starvation/circuit-breaker verdict, cmd.Process.Kill() then Wait() with a timeout (or use exec.CommandContext with the driver's iteration deadline) instead of assuming children exit when the driver decides to stop. Any io.Copy goroutine handed to cmd.Stdout must be abandoned — closing the read end unblocks it.

Secondary (same observation). hub process selfbuild-loop-v21 ran with restart=always, turning every intentional exit-0 starvation halt into an instant hollow restart — 133 restarts overnight (loop-209 log: 125 start banners, zero work). Intentional halts require restart=on-failure per the selfbuild-loop-ops skill; make loop-start/driver-side supervision should enforce this, not rely on operator memory.

Activity

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

    priority:P2Backlog — later iterations

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions