mirror of
https://github.com/stablyai/orca.git
synced 2026-10-31 00:57:45 +00:00
Give Windows taskkill a 5s budget to reduce flaky tree cleanup (#28577)
* Give Windows taskkill a 5s budget before tree cleanup is reported unveri On busy Windows machines, `taskkill` could take longer than the 2s budget used for other subprocesses. Tree termination then gave up before the process tree was confirmed gone. The taskkill timeout is now 5s, matching the other Windows tree-cleanup paths. Tests cover a slow taskkill that still verifies termination, and a hung taskkill that is bounded and falls back to SIGKILL. The batch-shim recovery test gets a longer hang and a 30s timeout so it has room on slow runners. * Pass the context clock into structured session option writes - Expose the injected `now` clock to the structured agent session option writer, so timestamps come from the same source as the rest of the context. - Update the main and renderer layout-writer baselines to match the reduced line counts in `src/main/ipc/session.ts` and the removed `set-active-folder-workspace.ts` entry.
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
1 src/main/ipc/renderer-shutdown-checkpoint.ts
|
||||
1 src/main/ipc/runtime-environment-removal-cleanup.ts
|
||||
1 src/main/ipc/runtime-environment-session-reconcile.ts
|
||||
3 src/main/ipc/session.ts
|
||||
2 src/main/ipc/session.ts
|
||||
6 src/main/orca-profiles/profile-project-session-state.ts
|
||||
4 src/main/orca-profiles/profile-project-source-removal.ts
|
||||
2 src/main/orca-profiles/profile-project-state-file.ts
|
||||
|
||||
@@ -102,7 +102,6 @@
|
||||
6 src/renderer/src/store/slices/terminal-orphan-helpers.ts
|
||||
4 src/renderer/src/store/slices/terminal-tab-title-batch.ts
|
||||
6 src/renderer/src/store/slices/terminals.ts
|
||||
5 src/renderer/src/store/slices/worktrees/session/set-active-folder-workspace.ts
|
||||
7 src/renderer/src/store/slices/worktrees/session/set-active-worktree.ts
|
||||
15 src/renderer/src/store/slices/worktrees/session/worktree-identity-rename-state.ts
|
||||
2 src/renderer/src/store/slices/worktrees/session/worktree-slice-lookups.ts
|
||||
|
||||
@@ -265,6 +265,7 @@ describe.runIf(process.platform === 'win32')('Windows preflight batch shims', ()
|
||||
}
|
||||
})
|
||||
|
||||
// Include the probe, tree-cleanup deadline, and recovery probe on a busy Windows runner.
|
||||
it('recovers after a hung batch launcher and terminates its Node child', async () => {
|
||||
const first = path.join(root, 'hung')
|
||||
const second = path.join(root, 'working')
|
||||
@@ -273,7 +274,7 @@ describe.runIf(process.platform === 'win32')('Windows preflight batch shims', ()
|
||||
const name = `${COMMAND}.CMD`
|
||||
await writeFile(
|
||||
path.join(first, 'hang.js'),
|
||||
`require('node:fs').writeFileSync(require('node:path').join(__dirname, 'child.pid'), String(process.pid)); setTimeout(function () {}, 30000);`
|
||||
`require('node:fs').writeFileSync(require('node:path').join(__dirname, 'child.pid'), String(process.pid)); setTimeout(function () {}, 60000);`
|
||||
)
|
||||
await writeFile(path.join(first, name), `@echo off\r\n"${process.execPath}" "%~dp0hang.js"\r\n`)
|
||||
await writeFile(
|
||||
@@ -290,5 +291,5 @@ describe.runIf(process.platform === 'win32')('Windows preflight batch shims', ()
|
||||
const childPid = Number(await readFile(path.join(first, 'child.pid'), 'utf8'))
|
||||
expect(Number.isSafeInteger(childPid) && childPid > 0).toBe(true)
|
||||
expect(() => process.kill(childPid, 0)).toThrow()
|
||||
}, 15_000)
|
||||
}, 30_000)
|
||||
})
|
||||
|
||||
@@ -19,6 +19,7 @@ export async function writeStructuredAgentSessionOption(
|
||||
const ctx = {
|
||||
sessionId,
|
||||
fence,
|
||||
now: () => context.now(),
|
||||
adapter: context.deps.adapter,
|
||||
now: context.now,
|
||||
persistOptions: (options: Readonly<Record<string, string>>) =>
|
||||
|
||||
@@ -105,6 +105,46 @@ describe('forceTerminateProcessTree', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it('allows a slow Windows taskkill to verify tree termination', async () => {
|
||||
await withWindows(async () => {
|
||||
vi.useFakeTimers()
|
||||
const child = mockProcess(1234)
|
||||
const taskkill = mockProcess(5678)
|
||||
spawnMock.mockReturnValue(taskkill)
|
||||
let settled = false
|
||||
const pending = forceTerminateProcessTree(child)
|
||||
void pending.then(() => {
|
||||
settled = true
|
||||
})
|
||||
|
||||
await vi.advanceTimersByTimeAsync(3_000)
|
||||
|
||||
expect(settled).toBe(false)
|
||||
expect(taskkill.kill).not.toHaveBeenCalled()
|
||||
expect(child.kill).not.toHaveBeenCalled()
|
||||
taskkill.emit('close', 0)
|
||||
await expect(pending).resolves.toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('bounds a hung Windows taskkill and leaves tree termination unverified', async () => {
|
||||
await withWindows(async () => {
|
||||
vi.useFakeTimers()
|
||||
const child = mockProcess(1234)
|
||||
const taskkill = mockProcess(5678)
|
||||
spawnMock.mockReturnValue(taskkill)
|
||||
const pending = forceTerminateProcessTree(child)
|
||||
|
||||
await vi.advanceTimersByTimeAsync(5_000)
|
||||
|
||||
await expect(pending).resolves.toBe(false)
|
||||
expect(taskkill.kill).toHaveBeenCalledOnce()
|
||||
expect(child.kill).toHaveBeenCalledWith('SIGKILL')
|
||||
taskkill.emit('close', 0)
|
||||
expect(child.kill).toHaveBeenCalledOnce()
|
||||
})
|
||||
})
|
||||
|
||||
it.skipIf(process.platform === 'win32')(
|
||||
'stops waiting when a POSIX process group cannot become quiescent',
|
||||
async () => {
|
||||
|
||||
@@ -4,6 +4,8 @@ import { windowsSystem32Binary } from './windows-system-binary'
|
||||
|
||||
const PROBE_INTERVAL_MS = 25
|
||||
const SUBPROCESS_TIMEOUT_MS = 2_000
|
||||
// Allow the same taskkill startup budget as the other Windows tree-cleanup paths.
|
||||
const WINDOWS_TASKKILL_TIMEOUT_MS = 5_000
|
||||
const MAX_PS_OUTPUT_BYTES = 8 * 1024 * 1024
|
||||
|
||||
/**
|
||||
@@ -131,7 +133,7 @@ function taskkillTree(
|
||||
const timer = setTimeout(() => {
|
||||
killer.kill()
|
||||
finish(true)
|
||||
}, SUBPROCESS_TIMEOUT_MS)
|
||||
}, WINDOWS_TASKKILL_TIMEOUT_MS)
|
||||
timer.unref?.()
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user