From 6b4978b428d33b6d5c8df540398a34870edd0e32 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 10 Mar 2026 20:22:07 +0700 Subject: [PATCH] Clean up Windows smoke relay shutdown --- .github/workflows/desktop-release.yml | 1 + .../desktop/scripts/managed-daemon-smoke.mjs | 43 ++++++++++++++++++- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/.github/workflows/desktop-release.yml b/.github/workflows/desktop-release.yml index 6ca3667be..d6e38a1bd 100644 --- a/.github/workflows/desktop-release.yml +++ b/.github/workflows/desktop-release.yml @@ -443,6 +443,7 @@ jobs: exit 1 - name: Smoke check managed runtime for Windows + timeout-minutes: 12 env: PASEO_MANAGED_SMOKE_SKIP_BUILD: "1" run: npm run smoke:managed-daemon --workspace=@getpaseo/desktop diff --git a/packages/desktop/scripts/managed-daemon-smoke.mjs b/packages/desktop/scripts/managed-daemon-smoke.mjs index 2eca7d71b..c7619bcee 100644 --- a/packages/desktop/scripts/managed-daemon-smoke.mjs +++ b/packages/desktop/scripts/managed-daemon-smoke.mjs @@ -110,6 +110,19 @@ function escapeForRegExp(value) { return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); } +async function waitForChildExit(child, timeoutMs) { + if (!child || child.exitCode !== null || child.killed) { + return; + } + await new Promise((resolve) => { + const timeout = setTimeout(resolve, timeoutMs); + child.once("exit", () => { + clearTimeout(timeout); + resolve(); + }); + }); +} + async function execFileWithTimeout(command, args, options, label) { try { return await execFileAsync(command, args, { @@ -141,6 +154,34 @@ async function runBinary(binaryPath, args, env) { }; } +async function terminateChildProcess(child, label) { + if (!child || child.exitCode !== null || child.killed) { + return; + } + if (process.platform === "win32" && typeof child.pid === "number") { + try { + await execFileWithTimeout( + "taskkill", + ["/pid", String(child.pid), "/T", "/F"], + { maxBuffer: 1024 * 1024 }, + `${label} taskkill` + ); + } catch {} + await waitForChildExit(child, 5_000); + return; + } + try { + child.kill("SIGTERM"); + } catch {} + await waitForChildExit(child, 5_000); + if (child.exitCode === null && !child.killed) { + try { + child.kill("SIGKILL"); + } catch {} + await waitForChildExit(child, 5_000); + } +} + async function runWorkspaceCli(args, env) { const { stdout, stderr } = await execFileWithTimeout( process.execPath, @@ -808,6 +849,6 @@ try { } } catch {} try { - relayProcess?.kill("SIGTERM"); + await terminateChildProcess(relayProcess, "local relay"); } catch {} }