early-ppid.ts 1.4 KB

12345678910111213141516171819202122232425
  1. /**
  2. * Parent-pid baseline captured as early as possible in process life (#1185).
  3. *
  4. * The PPID watchdog's POSIX signal is "`process.ppid` CHANGED since startup" —
  5. * but a launcher killed within the first ~100ms of our boot (an MCP host's
  6. * config probe, an instant user cancel, an initialize-timeout teardown) can
  7. * reparent this process to init BEFORE the serve/proxy code captured its
  8. * baseline. The baseline then reads `1`, never diverges, and the watchdog is
  9. * permanently blind — the orphaned-server accumulation reported in #1185.
  10. * Reproduced on macOS: SIGKILL the launcher 50ms after spawn while the host
  11. * holds the stdio pipes open, and the server survived indefinitely; at 150ms
  12. * the old capture had already run and the watchdog reaped it.
  13. *
  14. * The CLI entry imports this module before anything else, so the capture runs
  15. * within the first few ms of JS execution — the earliest a Node process can
  16. * observe its parent. A kill landing in the remaining pre-JS window (process
  17. * spawn → first require) still captures `1`; that residual case is covered by
  18. * the startup-handshake timeout (see ./startup-handshake.ts), which reaps a
  19. * server that never receives any MCP traffic.
  20. *
  21. * Library consumers don't load the CLI entry; for them the capture runs at
  22. * first import of the MCP layer — no worse than the previous per-call-site
  23. * capture, and identical once the module cache warms.
  24. */
  25. export const EARLY_PPID: number = process.ppid;