From f84f63ccd777aee8961f7631008a7f30a68faaa6 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Wed, 29 Jul 2026 08:26:21 +0800 Subject: [PATCH] test(runtime): finish zombie quiescence migration --- packages/lsp/lsp-local/tests/instance.spec.ts | 13 +++++++++++-- .../subprocess/subprocess-local/tests/spawn.spec.ts | 6 +++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/packages/lsp/lsp-local/tests/instance.spec.ts b/packages/lsp/lsp-local/tests/instance.spec.ts index 811f15c9fa..08bad67ae2 100644 --- a/packages/lsp/lsp-local/tests/instance.spec.ts +++ b/packages/lsp/lsp-local/tests/instance.spec.ts @@ -1,4 +1,5 @@ import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { readFileSync } from 'node:fs' import { mkdtemp, mkdir, readFile, rm, writeFile, realpath } from 'node:fs/promises' import { tmpdir } from 'node:os' import { join } from 'node:path' @@ -346,14 +347,22 @@ describe('LspInstance disposal', () => { function processAlive(pid: number): boolean { try { process.kill(pid, 0) - return true } catch (error) { if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false throw error } + if (process.platform !== 'linux') return true + try { + const stat = readFileSync(`/proc/${pid}/stat`, 'utf8') + const state = stat.slice(stat.lastIndexOf(')') + 2).split(/\s+/, 1)[0] + return !/^[ZXx]$/.test(state ?? '') + } catch (error) { + if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false + throw error + } } -/** Wait until a process id disappears so temporary-workspace cleanup cannot race handle release. */ +/** Wait until a process can no longer execute so temporary-workspace cleanup cannot race handle release. */ async function waitForProcessExit(pid: number, timeoutMs = 3_000): Promise { const started = Date.now() while (processAlive(pid)) { diff --git a/packages/subprocess/subprocess-local/tests/spawn.spec.ts b/packages/subprocess/subprocess-local/tests/spawn.spec.ts index b9f0bf0321..f28f741992 100644 --- a/packages/subprocess/subprocess-local/tests/spawn.spec.ts +++ b/packages/subprocess/subprocess-local/tests/spawn.spec.ts @@ -665,7 +665,7 @@ describe('tree-survivor escalation (terminate and bounded waits reach helpers th clearTimeout(timer) running.terminate() await expect(running.waitForExit()).resolves.toBe(true) - expect(() => process.kill(helper, 0)).toThrow() + await expect(waitGone(helper)).resolves.toBeUndefined() }) it('service teardown awaits tree survivors, not just handle settlement', async () => { @@ -682,8 +682,8 @@ describe('tree-survivor escalation (terminate and bounded waits reach helpers th const helper = await waitForPidFile(pidFile) await running.done await fiber.dispose() - // Teardown itself waited for the survivor to die. - expect(() => process.kill(helper, 0)).toThrow() + // Teardown itself waited for the survivor to become quiescent. + await expect(waitGone(helper)).resolves.toBeUndefined() }) })