From 46309fa346708fd87c47abb650039a2e7a67c874 Mon Sep 17 00:00:00 2001 From: Harry Brundage Date: Fri, 9 Feb 2024 00:18:51 +0000 Subject: [PATCH] Make zombie children clean themselves up The parent wds process can crash sometimes when watching too many files, or due to memory pressure on the system, or really any number of reasons. When this happens, the children become zombies and live forever. If the parent crashes though, they'll never be reloaded, and signals from the terminal won't be sent along to them, so they just accumulate and suck up memory on developer machines! Yuck! This adds active monitoring to the child wds processes so that they notice if the parent is gone, and kill themselves right away if so. This isn't 100% reliable, but this will at least reap most of em so we stop accumulating so much cruft. --- .github/workflows/test.yml | 2 +- {test => integration-test}/oom/package.json | 0 {test => integration-test}/oom/run.ts | 0 {test => integration-test}/oom/test.sh | 0 integration-test/parent-crash/package.json | 10 + integration-test/parent-crash/run.ts | 4 + integration-test/parent-crash/test.js | 50 ++++ .../reload/package.json | 0 integration-test/reload/run-scratch.ts | 10 + {test => integration-test}/reload/run.ts | 0 {test => integration-test}/reload/test.sh | 0 .../server/package.json | 0 {test => integration-test}/server/run.ts | 0 {test => integration-test}/server/test.sh | 0 .../simple/package.json | 0 {test => integration-test}/simple/run.ts | 0 {test => integration-test}/simple/test.sh | 0 {test => integration-test}/simple/utils.ts | 0 .../sourcemap/package.json | 0 {test => integration-test}/sourcemap/run.ts | 0 {test => integration-test}/sourcemap/test.sh | 0 {test => integration-test}/sourcemap/utils.ts | 0 {test => integration-test}/test.sh | 5 + jest.config.js | 1 + package.json | 3 +- pnpm-lock.yaml | 235 ++++++++++++++++++ src/child-process-registration.ts | 16 ++ 27 files changed, 334 insertions(+), 2 deletions(-) rename {test => integration-test}/oom/package.json (100%) rename {test => integration-test}/oom/run.ts (100%) rename {test => integration-test}/oom/test.sh (100%) create mode 100644 integration-test/parent-crash/package.json create mode 100644 integration-test/parent-crash/run.ts create mode 100755 integration-test/parent-crash/test.js rename {test => integration-test}/reload/package.json (100%) create mode 100644 integration-test/reload/run-scratch.ts rename {test => integration-test}/reload/run.ts (100%) rename {test => integration-test}/reload/test.sh (100%) rename {test => integration-test}/server/package.json (100%) rename {test => integration-test}/server/run.ts (100%) rename {test => integration-test}/server/test.sh (100%) rename {test => integration-test}/simple/package.json (100%) rename {test => integration-test}/simple/run.ts (100%) rename {test => integration-test}/simple/test.sh (100%) rename {test => integration-test}/simple/utils.ts (100%) rename {test => integration-test}/sourcemap/package.json (100%) rename {test => integration-test}/sourcemap/run.ts (100%) rename {test => integration-test}/sourcemap/test.sh (100%) rename {test => integration-test}/sourcemap/utils.ts (100%) rename {test => integration-test}/test.sh (79%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fa6791d..733e3ae 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v2 - uses: ./.github/actions/setup-test-env - run: pnpm build - - run: test/test.sh + - run: integration-test/test.sh - run: pnpm jest lint: diff --git a/test/oom/package.json b/integration-test/oom/package.json similarity index 100% rename from test/oom/package.json rename to integration-test/oom/package.json diff --git a/test/oom/run.ts b/integration-test/oom/run.ts similarity index 100% rename from test/oom/run.ts rename to integration-test/oom/run.ts diff --git a/test/oom/test.sh b/integration-test/oom/test.sh similarity index 100% rename from test/oom/test.sh rename to integration-test/oom/test.sh diff --git a/integration-test/parent-crash/package.json b/integration-test/parent-crash/package.json new file mode 100644 index 0000000..77088b7 --- /dev/null +++ b/integration-test/parent-crash/package.json @@ -0,0 +1,10 @@ +{ + "name": "parent-crash", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "license": "ISC" +} diff --git a/integration-test/parent-crash/run.ts b/integration-test/parent-crash/run.ts new file mode 100644 index 0000000..054d153 --- /dev/null +++ b/integration-test/parent-crash/run.ts @@ -0,0 +1,4 @@ +process.stderr.write("child started\n") +setInterval(() => { + process.stderr.write("child still alive\n") +}, 200) diff --git a/integration-test/parent-crash/test.js b/integration-test/parent-crash/test.js new file mode 100755 index 0000000..11fa627 --- /dev/null +++ b/integration-test/parent-crash/test.js @@ -0,0 +1,50 @@ +#!/usr/bin/env zx +const assert = require("assert"); +const { exec } = require("child_process"); + +async function getChildPids(parentPid, callback) { + const result = await $`pgrep -P ${parentPid}`; + return result.stdout + .split("\n") + .filter((pid) => pid) + .map((pid) => parseInt(pid, 10)); +} + +function processIsRunning(pid) { + try { + process.kill(pid, 0); + return true; + } catch (e) { + return false; + } +} + +const { setTimeout } = require("timers/promises"); + +const main = async () => { + // launch the wds process + const parent = $`${__dirname}/../../pkg/wds.bin.js --watch ${__dirname}/run.ts`.nothrow(); + + // wait for the wds process to start + await setTimeout(500); + + // get the pid of the child process that the parent wds supervisor will have started + const pids = await getChildPids(parent.child.pid); + assert(pids.length > 0, "no child pids found for supervisor process"); + + // SIGKILL the parent process, as if it OOMed or something like that to simulate a zombie child + console.log(`killing parent (${parent.child.pid})`); + await parent.kill(9); + assert.ok(processIsRunning(pids[0]), "test is broken, child process is not running immediately after parent is dead"); + + // ensure the children are dead too after their monitoring delay + await setTimeout(3000); + + for (const pid of pids) { + assert.ok(!processIsRunning(pid), `child process ${pid} is still running after parent has been killed`); + } + + await parent; +}; + +void main(); diff --git a/test/reload/package.json b/integration-test/reload/package.json similarity index 100% rename from test/reload/package.json rename to integration-test/reload/package.json diff --git a/integration-test/reload/run-scratch.ts b/integration-test/reload/run-scratch.ts new file mode 100644 index 0000000..a9a6b26 --- /dev/null +++ b/integration-test/reload/run-scratch.ts @@ -0,0 +1,10 @@ +const http = require("http"); + +const requestListener = function (req, res) { + res.writeHead(200); + res.end("Hey, Pluto!"); +}; + +const server = http.createServer(requestListener); +server.listen(8080); +console.warn("Listening on 8080"); diff --git a/test/reload/run.ts b/integration-test/reload/run.ts similarity index 100% rename from test/reload/run.ts rename to integration-test/reload/run.ts diff --git a/test/reload/test.sh b/integration-test/reload/test.sh similarity index 100% rename from test/reload/test.sh rename to integration-test/reload/test.sh diff --git a/test/server/package.json b/integration-test/server/package.json similarity index 100% rename from test/server/package.json rename to integration-test/server/package.json diff --git a/test/server/run.ts b/integration-test/server/run.ts similarity index 100% rename from test/server/run.ts rename to integration-test/server/run.ts diff --git a/test/server/test.sh b/integration-test/server/test.sh similarity index 100% rename from test/server/test.sh rename to integration-test/server/test.sh diff --git a/test/simple/package.json b/integration-test/simple/package.json similarity index 100% rename from test/simple/package.json rename to integration-test/simple/package.json diff --git a/test/simple/run.ts b/integration-test/simple/run.ts similarity index 100% rename from test/simple/run.ts rename to integration-test/simple/run.ts diff --git a/test/simple/test.sh b/integration-test/simple/test.sh similarity index 100% rename from test/simple/test.sh rename to integration-test/simple/test.sh diff --git a/test/simple/utils.ts b/integration-test/simple/utils.ts similarity index 100% rename from test/simple/utils.ts rename to integration-test/simple/utils.ts diff --git a/test/sourcemap/package.json b/integration-test/sourcemap/package.json similarity index 100% rename from test/sourcemap/package.json rename to integration-test/sourcemap/package.json diff --git a/test/sourcemap/run.ts b/integration-test/sourcemap/run.ts similarity index 100% rename from test/sourcemap/run.ts rename to integration-test/sourcemap/run.ts diff --git a/test/sourcemap/test.sh b/integration-test/sourcemap/test.sh similarity index 100% rename from test/sourcemap/test.sh rename to integration-test/sourcemap/test.sh diff --git a/test/sourcemap/utils.ts b/integration-test/sourcemap/utils.ts similarity index 100% rename from test/sourcemap/utils.ts rename to integration-test/sourcemap/utils.ts diff --git a/test/test.sh b/integration-test/test.sh similarity index 79% rename from test/test.sh rename to integration-test/test.sh index e81939e..1449895 100755 --- a/test/test.sh +++ b/integration-test/test.sh @@ -21,4 +21,9 @@ echo echo "::group::Reload test ${args}" bash $DIR/reload/test.sh $args echo "::endgroup::" +echo + +echo "::group::ParentCrash test ${args}" +node_modules/.bin/zx $DIR/parent-crash/test.js $args +echo "::endgroup::" echo \ No newline at end of file diff --git a/jest.config.js b/jest.config.js index d57534b..4f8f763 100644 --- a/jest.config.js +++ b/jest.config.js @@ -3,4 +3,5 @@ module.exports = { "^.+\\.[jt]sx?$": ["@swc/jest", { sourceMaps: "inline" }], }, testEnvironment: "node", + testMatch: ["/spec/**/?(*.)+(spec|test).[tj]s?(x)"], }; diff --git a/package.json b/package.json index b1a167f..be7ee35 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,8 @@ "gitpkg": "^1.0.0-beta.2", "jest": "^27.4.7", "prettier": "^2.8.8", - "typescript": "^5.1.3" + "typescript": "^5.1.3", + "zx": "^7.2.3" }, "packageManager": "pnpm@8.12.1+sha256.28ca61ece5a496148b73fabc9afb820f9c3fec4f55f04ce45a2cea0a5219f2e1" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 17e085e..3a6b10b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -76,6 +76,9 @@ devDependencies: typescript: specifier: ^5.1.3 version: 5.1.3 + zx: + specifier: ^7.2.3 + version: 7.2.3 packages: @@ -959,6 +962,13 @@ packages: resolution: {integrity: sha512-lGuMq71TL466jtCpvh7orGd+mrdBmo2h8ozvtOOTbq3ByfWpuN+UVxv4sOv3YpsD4NhW2k6ESGhnT/FIg4Ouzw==} dev: true + /@types/fs-extra@11.0.4: + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 18.19.15 + dev: true + /@types/glob@7.1.4: resolution: {integrity: sha512-w+LsMxKyYQm347Otw+IfBXOv9UWVjpHpCDdbBMt8Kz/xbvCYNjP+0qPh91Km3iKfSRLBB0P7fAMf0KHrPu+MyA==} dependencies: @@ -1003,6 +1013,12 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true + /@types/jsonfile@6.1.4: + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + dependencies: + '@types/node': 18.19.15 + dev: true + /@types/lodash@4.14.194: resolution: {integrity: sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==} dev: true @@ -1011,14 +1027,28 @@ packages: resolution: {integrity: sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==} dev: true + /@types/minimist@1.2.5: + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + dev: true + /@types/node@18.11.9: resolution: {integrity: sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==} dev: true + /@types/node@18.19.15: + resolution: {integrity: sha512-AMZ2UWx+woHNfM11PyAEQmfSxi05jm9OlkxczuHeEqmvwPkYj6MWv44gbzDPefYOLysTOFyI3ziiy2ONmUZfpA==} + dependencies: + undici-types: 5.26.5 + dev: true + /@types/prettier@2.7.3: resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} dev: true + /@types/ps-tree@1.1.6: + resolution: {integrity: sha512-PtrlVaOaI44/3pl3cvnlK+GxOM3re2526TJvPvh7W+keHIXdV4TE0ylpPBAcvFQCbGitaTXwL9u+RF7qtVeazQ==} + dev: true + /@types/semver@7.5.0: resolution: {integrity: sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==} dev: true @@ -1027,6 +1057,10 @@ packages: resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} dev: true + /@types/which@3.0.3: + resolution: {integrity: sha512-2C1+XoY0huExTbs8MQv1DuS5FS86+SEjdM9F/+GS61gg5Hqbtj8ZiDSx8MfWcyei907fIPbfPGCOrNUTnVHY1g==} + dev: true + /@types/yargs-parser@20.2.0: resolution: {integrity: sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA==} dev: true @@ -1554,6 +1588,11 @@ packages: supports-color: 7.2.0 dev: true + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + /char-regex@1.0.2: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} @@ -1696,6 +1735,11 @@ packages: cssom: 0.3.8 dev: true + /data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + dev: true + /data-urls@2.0.0: resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} engines: {node: '>=10'} @@ -1827,6 +1871,10 @@ packages: webidl-conversions: 5.0.0 dev: true + /duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + dev: true + /electron-to-chromium@1.4.508: resolution: {integrity: sha512-FFa8QKjQK/A5QuFr2167myhMesGrhlOBD+3cYNxO9/S4XzHEXesyTD/1/xF644gC8buFPz3ca6G1LOQD0tZrrg==} dev: true @@ -2270,6 +2318,18 @@ packages: engines: {node: '>=0.10.0'} dev: true + /event-stream@3.3.4: + resolution: {integrity: sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==} + dependencies: + duplexer: 0.1.2 + from: 0.1.7 + map-stream: 0.1.0 + pause-stream: 0.0.11 + split: 0.3.3 + stream-combiner: 0.0.4 + through: 2.3.8 + dev: true + /execa@4.1.0: resolution: {integrity: sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==} engines: {node: '>=10'} @@ -2329,6 +2389,17 @@ packages: merge2: 1.4.1 micromatch: 4.0.4 + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.4 + dev: true + /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true @@ -2348,6 +2419,14 @@ packages: bser: 2.1.1 dev: true + /fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.2 + dev: true + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -2413,10 +2492,30 @@ packages: mime-types: 2.1.35 dev: true + /formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: true + + /from@0.1.7: + resolution: {integrity: sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==} + dev: true + /fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} dev: true + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.9 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -2446,6 +2545,11 @@ packages: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} dev: true + /fx@31.0.0: + resolution: {integrity: sha512-OoeYSPKqNKmfnH4s+rGYI0c8OZmqqOOXsUtqy0YyHqQQoQSDiDs3m3M9uXKx5OQR+jDx7/FhYqpO3kl/As/xgg==} + hasBin: true + dev: true + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -2588,6 +2692,17 @@ packages: merge2: 1.4.1 slash: 3.0.0 + /globby@13.2.2: + resolution: {integrity: sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 4.0.0 + dev: true + /globby@7.1.1: resolution: {integrity: sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==} engines: {node: '>=4'} @@ -2719,6 +2834,11 @@ packages: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} + engines: {node: '>= 4'} + dev: true + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -3547,6 +3667,14 @@ packages: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} dev: true + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.9 + dev: true + /jsx-ast-utils@3.3.3: resolution: {integrity: sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==} engines: {node: '>=4.0'} @@ -3654,6 +3782,10 @@ packages: tmpl: 1.0.5 dev: true + /map-stream@0.1.0: + resolution: {integrity: sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==} + dev: true + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -3720,6 +3852,20 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: true + + /node-fetch@3.3.1: + resolution: {integrity: sha512-cRVc/kyto/7E5shrWca1Wsea4y6tL9iYJE5FBCius3JQfb/4P4I295PfhgbJQBLTx6lATE4z+wK0rPM4VS2uow==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + dev: true + /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: true @@ -3936,6 +4082,12 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + /pause-stream@0.0.11: + resolution: {integrity: sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==} + dependencies: + through: 2.3.8 + dev: true + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -4021,6 +4173,14 @@ packages: react-is: 16.13.1 dev: true + /ps-tree@1.2.0: + resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} + engines: {node: '>= 0.10'} + hasBin: true + dependencies: + event-stream: 3.3.4 + dev: true + /psl@1.9.0: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: true @@ -4243,6 +4403,11 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + /slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + dev: true + /source-map-support@0.5.21: resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: @@ -4275,6 +4440,12 @@ packages: resolution: {integrity: sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==} dev: true + /split@0.3.3: + resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} + dependencies: + through: 2.3.8 + dev: true + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true @@ -4286,6 +4457,12 @@ packages: escape-string-regexp: 2.0.0 dev: true + /stream-combiner@0.0.4: + resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==} + dependencies: + duplexer: 0.1.2 + dev: true + /string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -4455,6 +4632,10 @@ packages: resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} dev: true + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + /tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true @@ -4561,11 +4742,20 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} dev: true + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + /update-browserslist-db@1.0.11(browserslist@4.21.10): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true @@ -4629,6 +4819,11 @@ packages: defaults: 1.0.3 dev: true + /web-streams-polyfill@3.3.2: + resolution: {integrity: sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==} + engines: {node: '>= 8'} + dev: true + /webidl-conversions@5.0.0: resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} engines: {node: '>=8'} @@ -4639,6 +4834,11 @@ packages: engines: {node: '>=10.4'} dev: true + /webpod@0.0.2: + resolution: {integrity: sha512-cSwwQIeg8v4i3p4ajHhwgR7N6VyxAf+KYSSsY6Pd3aETE+xEU4vbitz7qQkB0I321xnhDdgtxuiSfk5r/FVtjg==} + hasBin: true + dev: true + /whatwg-encoding@1.0.5: resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} dependencies: @@ -4692,6 +4892,14 @@ packages: isexe: 2.0.0 dev: true + /which@3.0.1: + resolution: {integrity: sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + /word-wrap@1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} @@ -4764,6 +4972,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + /yargs-parser@18.1.3: resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==} engines: {node: '>=6'} @@ -4808,3 +5021,25 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + + /zx@7.2.3: + resolution: {integrity: sha512-QODu38nLlYXg/B/Gw7ZKiZrvPkEsjPN3LQ5JFXM7h0JvwhEdPNNl+4Ao1y4+o3CLNiDUNcwzQYZ4/Ko7kKzCMA==} + engines: {node: '>= 16.0.0'} + hasBin: true + dependencies: + '@types/fs-extra': 11.0.4 + '@types/minimist': 1.2.5 + '@types/node': 18.19.15 + '@types/ps-tree': 1.1.6 + '@types/which': 3.0.3 + chalk: 5.3.0 + fs-extra: 11.2.0 + fx: 31.0.0 + globby: 13.2.2 + minimist: 1.2.8 + node-fetch: 3.3.1 + ps-tree: 1.2.0 + webpod: 0.0.2 + which: 3.0.1 + yaml: 2.3.4 + dev: true diff --git a/src/child-process-registration.ts b/src/child-process-registration.ts index caa14f7..784981b 100644 --- a/src/child-process-registration.ts +++ b/src/child-process-registration.ts @@ -79,4 +79,20 @@ if (!workerData || !(workerData as SyncWorkerData).isWDSSyncWorker) { } }; } + + // monitor the parent process' health, if it dies, kill ourselves so we don't end up a zombie + const monitor = setInterval(() => { + try { + process.kill(process.ppid, 0); + // No error means the process exists + } catch (e) { + // An error means the process does not exist + log.error("wds parent process crashed, killing child"); + process.kill(-1 * process.pid, "SIGKILL"); + } + }, 1000); + monitor.unref(); + process.on("beforeExit", () => { + clearInterval(monitor); + }); }