Skip to content

Idle park SIGKILLs a session that still has background work running #204

Description

@prkl78

MonoCode version: 0.1.44
OS: macOS 26.6.2
Provider CLI: Claude Code 2.1.270

Correction: my original diagnosis was wrong — cd is not the trigger, and I could not reproduce my own steps. The real trigger is the 5-minute idle park. Original text struck through below, corrected report after it.

What happened (superseded)

Changing the working directory mid-session respawns the harness, and the respawn SIGKILLs the previous process group. Every process the agent had backgrounded dies with it, exit 137, with no error surfaced anywhere.

1. src-tauri/src/harness.rs:750 — the harness child gets process_group(0)
2. src/lib/harness/claude.ts:345 — a cwd change forces a fresh spawn
3. src-tauri/src/harness.rs:143, :332 — installing the new spawn calls terminate(prev.pid)
4. src-tauri/src/harness.rs:865 — that sends kill(-pid, SIGKILL) to the whole group

Backgrounded work is a grandchild in that group, so it is reaped too. nohup does not help; SIGKILL cannot be caught.

Steps to reproduce (superseded)

1. cd /tmp/dir-a 2. sleep 600 & 3. cd /tmp/dir-b 4. Job is gone, exit 137.

Suggested fix (superseded)

src-tauri/src/pty.rs:273 already does the right thing for terminals: setsid() puts each shell in its own session so it outlives the harness.


Corrected report

What happens

registry.ts:137 arms HARNESS_IDLE_PARK_MS (5 min, registry.ts:76) in the finally of every turn. If no new message arrives before it fires, registry.ts:91 calls stopHarnessSessionstopClaudeSessionkillChildterminate(pid)kill(-pid, SIGKILL) (harness.rs:776). The whole group goes: the CLI process, its in-process subagents, and anything the agent backgrounded.

The timer measures silence, not idleness. A session busy with a background workflow or a long script reads as idle.

Steps to reproduce

  1. Ask the agent to start background work lasting more than 5 minutes — a background workflow, or a run_in_background shell loop.
  2. Let the turn end.
  3. Send nothing for 5 minutes.
  4. Everything is gone.

Evidence

  • Controlled: two background agents, each ticking every 10 seconds toward 600s. Both stopped right around 300 — 4:50 and 4:40 of real runtime.
  • Real, twice: a research workflow lost 4 of 11 agents 5:00.32 after its turn ended; an App Store upload session lost 3 background pollers at 5:00.45, 5:00.22 and 5:00.32 after theirs.

Why it's a bug

Parking an idle session is reasonable — it resumes on the next message. The defect is that nothing checks for work in flight before the kill.

A guard for exactly this already exists: claude.ts:1268 holds the turn open while live.agentTasks is non-empty, which is why foreground work is safe. Backgrounded tasks don't register there, so the turn settles and the timer arms underneath them.

setsid() alone would not fix it. It would save shell-backgrounded jobs, but subagents run inside the CLI process — no child PIDs under it in any of my tests — so parking kills them whatever their process group.

The kill mechanism described in the original report still holds; only the trigger was wrong.

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

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions