




















@@ -767,6 +767,72 @@ describe("bundled plugin install/uninstall probe", () => {
767767},
768768);
769769770+it.runIf(process.platform !== "win32")(
771+"keeps closed runtime command groups tracked for parent cleanup",
772+async () => {
773+const root = makePackageRoot();
774+const commandPath = path.join(root, "closed-command.mjs");
775+const runnerPath = path.join(root, "run-closed-runtime-command.mjs");
776+const commandSettledPath = path.join(root, "command-settled");
777+const descendantPidPath = path.join(root, "closed-command-descendant.pid");
778+const descendantScript = [
779+"import fs from 'node:fs';",
780+`fs.writeFileSync(${JSON.stringify(descendantPidPath)}, String(process.pid));`,
781+"process.on('SIGTERM', () => {});",
782+"setInterval(() => {}, 1000);",
783+].join("\n");
784+fs.writeFileSync(
785+commandPath,
786+[
787+"import childProcess from 'node:child_process';",
788+`const child = childProcess.spawn(process.execPath, ["--input-type=module", "--eval", ${JSON.stringify(
789+ descendantScript,
790+ )}], { stdio: "ignore" });`,
791+"child.unref();",
792+"",
793+].join("\n"),
794+"utf8",
795+);
796+fs.writeFileSync(
797+runnerPath,
798+[
799+"import fs from 'node:fs';",
800+`const runtimeSmoke = await import(${JSON.stringify(pathToFileURL(runtimeSmokePath).href)});`,
801+`runtimeSmoke.runCommand(process.execPath, [${JSON.stringify(commandPath)}], {`,
802+" timeoutMs: 60_000,",
803+"}).finally(() => {",
804+` fs.writeFileSync(${JSON.stringify(commandSettledPath)}, "1");`,
805+"});",
806+"setInterval(() => {}, 1000);",
807+"",
808+].join("\n"),
809+"utf8",
810+);
811+812+const runner = spawn(process.execPath, [runnerPath], {
813+stdio: "ignore",
814+});
815+let descendantPid: number | undefined;
816+try {
817+await waitForFile(descendantPidPath, 1000);
818+descendantPid = Number(fs.readFileSync(descendantPidPath, "utf8"));
819+expect(pidIsAlive(descendantPid)).toBe(true);
820+await waitForFile(commandSettledPath, 1000);
821+822+runner.kill("SIGTERM");
823+824+await waitForDead(descendantPid, 2000);
825+} finally {
826+if (runner.pid && pidIsAlive(runner.pid)) {
827+runner.kill("SIGKILL");
828+}
829+if (descendantPid !== undefined && pidIsAlive(descendantPid)) {
830+process.kill(descendantPid, "SIGKILL");
831+}
832+}
833+},
834+);
835+770836it.runIf(process.platform !== "win32")(
771837"cleans detached runtime gateway groups when the parent is signaled",
772838async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。