Skip to content

fix(pi-subagents): terminate children recursively when parent process dies - #40

Merged
tasercake merged 2 commits into
mainfrom
worktree/pi-subagents-lifeline-20260724185355
Jul 24, 2026
Merged

fix(pi-subagents): terminate children recursively when parent process dies#40
tasercake merged 2 commits into
mainfrom
worktree/pi-subagents-lifeline-20260724185355

Conversation

@tasercake

Copy link
Copy Markdown
Owner

Summary

Child Pi subagents now self-terminate when their owning parent Pi session/process dies. This uses an extension-local anonymous lifeline pipe on stdin (fd 0) — zero extra FDs, zero new OS objects, zero external dependencies.

Architecture

  • Each parent spawns each child with stdio: [pipe, pipe, pipe] — stdin becomes the lifeline
  • Parent holds child.stdin open without writing; the child runtime watches fd 0 for EOF
  • When the parent process dies (even abruptly via SIGKILL), the kernel closes all FDs; the child sees EOF on fd 0 and self-terminates via SIGTERM
  • Recursive cascade is automatic: every child uses the same mechanism, so parent death → child EOF/termination → grandchild EOF/termination
  • Lifelines are closed on session_shutdown (session replacement) but NOT on agent_end (background children survive turns)
  • Normal child completion also releases the lifeline
  • Timeout semantics unchanged: timeout notifies and does not kill

Changes

File Change
src/runs/shared/subagent-prompt-runtime.ts Export PI_SUBAGENT_LIFELINE_FD env constant; add module-level lifeline watcher that listens for EOF on the lifeline fd and self-SIGTERMs
src/extension/index.ts Import lifeline env; change spawn stdio to [pipe, pipe, pipe]; manage lifelines map; close on completion and session_shutdown
test/unit/minimal-subagents.test.ts 6 new tests covering the full lifeline contract

Validation

  • 40 tests pass (1 pre-existing skip unchanged), including all prior tests preserved
  • 6 new lifeline tests all green:
    • lifeline env constant export — the runtime exposes the env var
    • prompt runtime sets up EOF watcher — the runtime registers the watcher when env is present
    • session_shutdown terminates children via lifeline — closing lifeline kills real child process
    • agent_end does NOT kill child process — background children survive turns
    • abrupt parent SIGKILL cascades to child termination — killing a real parent process causes its real child to exit promptly
    • recursive cascade — grandparent death kills parent subagent — killing the grandparent causes the parent subagent to die (and by extension any grandchildren)
  • Headless liveness test updated to match new stdio pattern and still passes
  • All timeout, cohort, widget, and notification tests unaffected

… dies

Add an extension-local anonymous lifeline pipe (stdin/fd 0) that lets
managed subagent children detect parent process death.  When the parent
dies (even SIGKILL), the kernel closes the write end of the pipe; the
child's prompt runtime watches the read end for EOF and self-terminates
via SIGTERM.  Because every recursively spawned child uses the same
mechanism, the cascade is automatic: parent death → child EOF/termination
→ grandchild EOF/termination.

Key design decisions:
- stdin fd 0 reused as lifeline (zero extra FDs, zero new OS objects)
- Lifeline closed on session_shutdown (session replacement) but NOT on
  agent_end (background children survive turns)
- Normal child completion also releases the lifeline
- Timeout semantics unchanged: timeout notifies and does not kill

Tests added (6 new, all passing):
- lifeline env constant export
- prompt runtime sets up EOF watcher on lifeline fd
- session_shutdown terminates children via lifeline
- agent_end does NOT kill children
- abrupt parent SIGKILL cascades to real child termination
- recursive cascade: grandparent death → parent subagent death
@tasercake
tasercake merged commit 433ce5a into main Jul 24, 2026
@tasercake
tasercake deleted the worktree/pi-subagents-lifeline-20260724185355 branch July 24, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant