






















11// Tui Pty Test Watch script supports OpenClaw repository automation.
2-import { spawn } from "node:child_process";
2+import { spawn, spawnSync } from "node:child_process";
33import { mkdir, open, writeFile } from "node:fs/promises";
44import { createRequire } from "node:module";
55import path from "node:path";
@@ -46,6 +46,12 @@ type ChildStopper = {
46464747type SignalChild = (child: KillableChild, signal: NodeJS.Signals) => void;
484849+type RunTaskkill = (
50+command: string,
51+args: string[],
52+options: { stdio: "ignore" },
53+) => { error?: unknown; status?: number | null } | undefined;
54+4955function unrefTimer(timer: ReturnType<typeof setTimeout>): void {
5056(timer as { unref?: () => void }).unref?.();
5157}
@@ -131,8 +137,44 @@ function currentTerminalDimension(value: number | undefined, fallback: number):
131137return String(value && value > 0 ? value : fallback);
132138}
133139134-function signalChildProcessTree(child: KillableChild, signal: NodeJS.Signals): void {
135-if (process.platform !== "win32" && typeof child.pid === "number") {
140+function signalWindowsProcessTree(
141+pid: number,
142+signal: NodeJS.Signals,
143+runTaskkill: RunTaskkill = spawnSync,
144+): boolean {
145+const args = ["/PID", String(pid), "/T"];
146+if (signal === "SIGKILL") {
147+args.push("/F");
148+}
149+const result = runTaskkill("taskkill", args, { stdio: "ignore" });
150+return !result?.error && result?.status === 0;
151+}
152+153+function signalWindowsProcessTreeOrForce(
154+pid: number,
155+signal: NodeJS.Signals,
156+runTaskkill: RunTaskkill = spawnSync,
157+): boolean {
158+if (signalWindowsProcessTree(pid, signal, runTaskkill)) {
159+return true;
160+}
161+return signal !== "SIGKILL" && signalWindowsProcessTree(pid, "SIGKILL", runTaskkill);
162+}
163+164+function signalChildProcessTree(
165+child: KillableChild,
166+signal: NodeJS.Signals,
167+{
168+ platform = process.platform,
169+ runTaskkill = spawnSync,
170+ useProcessGroup = platform !== "win32",
171+}: {
172+platform?: NodeJS.Platform;
173+runTaskkill?: RunTaskkill;
174+useProcessGroup?: boolean;
175+} = {},
176+): void {
177+if (useProcessGroup && typeof child.pid === "number") {
136178try {
137179process.kill(-child.pid, signal);
138180return;
@@ -141,6 +183,11 @@ function signalChildProcessTree(child: KillableChild, signal: NodeJS.Signals): v
141183// still useful on platforms without process groups.
142184}
143185}
186+if (platform === "win32" && typeof child.pid === "number") {
187+if (signalWindowsProcessTreeOrForce(child.pid, signal, runTaskkill)) {
188+return;
189+}
190+}
144191child.kill(signal);
145192}
146193此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。