From 2302212cc5beebd96716de1a65375896d3bdeec4 Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Fri, 21 Aug 2026 02:37:56 -0700 Subject: [PATCH] test(windows): pin that a child can still break away from the job Verified on Windows 11: 'start /b' writes its marker and no access-denied appears. Without JOB_OBJECT_LIMIT_BREAKAWAY_OK this fails, and it fails only inside an Orca terminal -- so the failure would look like Orca corrupting unrelated software rather than like a job-object change. --- .../windows/windows-pty-job.win32.test.ts | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/windows/windows-pty-job.win32.test.ts b/src/main/windows/windows-pty-job.win32.test.ts index 7dd8df31309..da87143082f 100644 --- a/src/main/windows/windows-pty-job.win32.test.ts +++ b/src/main/windows/windows-pty-job.win32.test.ts @@ -1,4 +1,7 @@ -import { afterEach, describe, expect, it } from 'vitest' +import { existsSync, mkdtempSync, rmSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, describe, expect, it, vi } from 'vitest' import type { IPty } from 'node-pty' import { isPtyJobOwnershipAvailable, @@ -130,6 +133,33 @@ describeOnWindows('ConPTY job ownership', () => { } }, 60_000) + it('still lets a child break away from the job', async () => { + // A job with no limits denies CREATE_BREAKAWAY_FROM_JOB outright, and + // installers, msiexec and some updater paths spawn that way deliberately. + // They would fail ONLY inside an Orca terminal, which is the worst shape a + // bug report can take, so JOB_OBJECT_LIMIT_BREAKAWAY_OK is load-bearing. + const nodePty = await import('node-pty') + const marker = join(mkdtempSync(join(tmpdir(), 'orca-breakaway-')), 'marker.txt') + const proc = nodePty.spawn('cmd.exe', [], { + name: 'xterm-256color', + cols: 100, + rows: 30, + cwd: tmpdir(), + useConptyDll: true + }) + spawned.push(proc) + + let output = '' + proc.onData((chunk) => { + output += chunk + }) + proc.write(`start /b cmd /c "echo ORCA_BREAKAWAY> ${marker}"\r`) + + await vi.waitFor(() => expect(existsSync(marker)).toBe(true), { timeout: 15_000 }) + expect(output).not.toMatch(/Access is denied/i) + rmSync(marker, { force: true }) + }, 60_000) + it('stops answering once the tree is gone, rather than claiming it is empty', async () => { // Measured, not assumed: node-pty drops its handle record and closes the // job when the shell exits, so a dead tree is unverifiable here rather than