Files
orca/src/shared/relay-optional-artifacts.test.ts
T
Neil aa3ae6f56e fix(ssh): close the pty master fd leak on relay hosts too (#17920)
* fix(ssh): close the pty master fd leak on Linux relay hosts

The app gets the FD_CLOEXEC patch through pnpm patchedDependencies (#17914);
the relay installs stock node-pty from npm, where no pnpm patch reaches. Linux
is where that matters -- it is the only relay platform that takes forkpty()'s
no-atomic-O_CLOEXEC path, and it is also the only one that already compiles
node-pty at install time, so the fix costs a second compile rather than a first.

Ships the patch as a relay asset applied like the existing Windows console-list
one, and rebuilds only after the probe has proven node-pty loadable. The rebuild
is non-fatal by construction: the working build is moved aside first and moved
back on any failure, a failed attempt drops a skip marker so the compile is
attempted at most once per relay directory, and the caller swallows the whole
step. macOS and Windows relays never run it.

Measured on node:22 with a relay-style npm install: before, the master is
cloexec=false and shows up as `26 -> /dev/pts/ptmx` in both a later pty child
and a later child_process child; after, cloexec=true and neither child sees it.

Closes #17915.

* test(ssh): feed the cloexec patch exec to the hand-rolled namespace fixtures

These sequences are positional, so the new Linux-only patch exec swallowed the
READY slot and every install/repair case timed out waiting for the relay.

* fix(ssh): patch the pty master before publishing the shared native-deps tree

* fix(ssh): refuse to publish a native-deps tree whose cloexec patch did not take
2026-09-02 03:02:27 -07:00

43 lines
1.9 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import {
RELAY_WINDOWS_PROCESS_TREE_FILENAME,
relayArtifactFilenames,
relayOptionalArtifactFilenames
} from './relay-artifacts'
describe('optional relay artifacts', () => {
it('keeps the process-table addon out of the required set', () => {
// The remote install probe requires every name this returns. Demanding an
// artifact only a Windows build machine can emit would make a correct relay
// read as MISSING forever and redeploy on every connect.
expect(relayArtifactFilenames(true)).not.toContain(RELAY_WINDOWS_PROCESS_TREE_FILENAME)
expect(relayOptionalArtifactFilenames(true)).toContain(RELAY_WINDOWS_PROCESS_TREE_FILENAME)
})
it('never offers it to a non-Windows host', () => {
expect(relayOptionalArtifactFilenames(false)).not.toContain(RELAY_WINDOWS_PROCESS_TREE_FILENAME)
expect(relayOptionalArtifactFilenames(false)).toEqual([])
})
it('keeps required and optional sets disjoint', () => {
for (const isWindows of [true, false]) {
const required = relayArtifactFilenames(isWindows)
const optional = relayOptionalArtifactFilenames(isWindows)
expect(optional.filter((name) => required.includes(name))).toEqual([])
}
})
it('still requires everything a relay cannot run without', () => {
expect(relayArtifactFilenames(true)).toContain('relay.js')
expect(relayArtifactFilenames(true)).toContain('node-pty-1.1.0-console-list-agent-patch.cjs')
})
it('ships the pty-master cloexec patch to every platform', () => {
// Only Linux runs it, but its bytes are what change the relay content hash, and therefore what
// moves an upgrading host to a fresh directory whose install can apply it (#17915).
for (const isWindows of [true, false]) {
expect(relayArtifactFilenames(isWindows)).toContain('node-pty-1.1.0-master-cloexec-patch.cjs')
}
})
})