Skip to content

feat(watchdog): pipe-based POLLHUP parent death detection#278

Merged
DorianZheng merged 1 commit intomainfrom
feat/watchdog-pipe-pollhup
Feb 16, 2026
Merged

feat(watchdog): pipe-based POLLHUP parent death detection#278
DorianZheng merged 1 commit intomainfrom
feat/watchdog-pipe-pollhup

Conversation

@DorianZheng
Copy link
Copy Markdown
Member

Summary

  • Replace kill(parent_pid, 0) polling with the pipe trick for parent death detection — zero latency, kernel-mediated, works across PID/mount namespaces
  • New watchdog module with Keepalive/ChildSetup types; parent holds write end, shim polls read end for POLLHUP
  • JailerBuilder gains preserved_fd support to inherit the watchdog pipe through pre_exec FD cleanup
  • ShimSpawner struct replaces spawn_subprocess() free function, returning SpawnedShim with child + keepalive
  • ShimHandler stores Keepalive for defense-in-depth (dropping handler triggers shim shutdown even if stop() is never called)
  • Remove parent_pid from InstanceSpec (no longer needed)

Test plan

  • Unit tests: watchdog pipe creation, FD validity, close behavior, POLLHUP delivery (4 tests)
  • Unit tests: JailerBuilder preserved_fd, pre_exec FD handling, ShimSpawner args (12 tests)
  • Integration test: non_detached_box_exits_on_runtime_drop — verifies full chain: Keepalive drop → pipe close → POLLHUP → SIGTERM → shim exit
  • Symmetric pair with existing detached_box_survives_runtime_drop (detached boxes survive, non-detached boxes exit)
  • cargo clippy --tests clean, cargo fmt clean

Replace `kill(parent_pid, 0)` polling loop with the "pipe trick" for
parent death detection. The parent holds the write end of a pipe; the
shim polls the read end. When the parent dies or drops the Keepalive,
the kernel closes the write end, delivering POLLHUP immediately — zero
latency, works across PID/mount namespaces.

Key changes:
- New watchdog module with Keepalive/ChildSetup types and PIPE_FD constant
- JailerBuilder gains preserved_fd support for FD inheritance through pre_exec
- ShimSpawner struct replaces spawn_subprocess() free function
- ShimHandler stores Keepalive for defense-in-depth (drop triggers shutdown)
- Shim's parent watchdog rewritten to use poll() on inherited pipe FD
- Remove parent_pid from InstanceSpec (no longer needed)
- Integration test: non_detached_box_exits_on_runtime_drop (symmetric
  counterpart to detached_box_survives_runtime_drop)
@DorianZheng DorianZheng merged commit 97c06ba into main Feb 16, 2026
14 checks passed
@DorianZheng DorianZheng deleted the feat/watchdog-pipe-pollhup branch February 16, 2026 18:26
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