watchdog.js 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. // this spawns a child process that listens for SIGHUP when the
  2. // parent process exits, and after 200ms, sends a SIGKILL to the
  3. // child, in case it did not terminate.
  4. import { spawn } from 'child_process';
  5. const watchdogCode = String.raw `
  6. const pid = parseInt(process.argv[1], 10)
  7. process.title = 'node (foreground-child watchdog pid=' + pid + ')'
  8. if (!isNaN(pid)) {
  9. let barked = false
  10. // keepalive
  11. const interval = setInterval(() => {}, 60000)
  12. const bark = () => {
  13. clearInterval(interval)
  14. if (barked) return
  15. barked = true
  16. process.removeListener('SIGHUP', bark)
  17. setTimeout(() => {
  18. try {
  19. process.kill(pid, 'SIGKILL')
  20. setTimeout(() => process.exit(), 200)
  21. } catch (_) {}
  22. }, 500)
  23. })
  24. process.on('SIGHUP', bark)
  25. }
  26. `;
  27. /**
  28. * Pass in a ChildProcess, and this will spawn a watchdog process that
  29. * will make sure it exits if the parent does, thus preventing any
  30. * dangling detached zombie processes.
  31. *
  32. * If the child ends before the parent, then the watchdog will terminate.
  33. */
  34. export const watchdog = (child) => {
  35. let dogExited = false;
  36. const dog = spawn(process.execPath, ['-e', watchdogCode, String(child.pid)], {
  37. stdio: 'ignore',
  38. });
  39. dog.on('exit', () => (dogExited = true));
  40. child.on('exit', () => {
  41. if (!dogExited)
  42. dog.kill('SIGKILL');
  43. });
  44. return dog;
  45. };
  46. //# sourceMappingURL=watchdog.js.map