test(runtime): finish zombie quiescence migration
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
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 { mkdtemp, mkdir, readFile, rm, writeFile, realpath } from 'node:fs/promises'
|
||||||
import { tmpdir } from 'node:os'
|
import { tmpdir } from 'node:os'
|
||||||
import { join } from 'node:path'
|
import { join } from 'node:path'
|
||||||
@@ -346,14 +347,22 @@ describe('LspInstance disposal', () => {
|
|||||||
function processAlive(pid: number): boolean {
|
function processAlive(pid: number): boolean {
|
||||||
try {
|
try {
|
||||||
process.kill(pid, 0)
|
process.kill(pid, 0)
|
||||||
return true
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false
|
if ((error as NodeJS.ErrnoException).code === 'ESRCH') return false
|
||||||
throw error
|
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<void> {
|
async function waitForProcessExit(pid: number, timeoutMs = 3_000): Promise<void> {
|
||||||
const started = Date.now()
|
const started = Date.now()
|
||||||
while (processAlive(pid)) {
|
while (processAlive(pid)) {
|
||||||
|
|||||||
@@ -665,7 +665,7 @@ describe('tree-survivor escalation (terminate and bounded waits reach helpers th
|
|||||||
clearTimeout(timer)
|
clearTimeout(timer)
|
||||||
running.terminate()
|
running.terminate()
|
||||||
await expect(running.waitForExit()).resolves.toBe(true)
|
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 () => {
|
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)
|
const helper = await waitForPidFile(pidFile)
|
||||||
await running.done
|
await running.done
|
||||||
await fiber.dispose()
|
await fiber.dispose()
|
||||||
// Teardown itself waited for the survivor to die.
|
// Teardown itself waited for the survivor to become quiescent.
|
||||||
expect(() => process.kill(helper, 0)).toThrow()
|
await expect(waitGone(helper)).resolves.toBeUndefined()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user