fix(linux): preserve unverified external displays

This commit is contained in:
Neil
2026-09-01 03:25:56 -07:00
parent 4437674a2f
commit 3695bfc4cb
2 changed files with 24 additions and 27 deletions
+12 -25
View File
@@ -119,34 +119,21 @@ describe('ensureVirtualDisplayForHeadlessServe', () => {
expect(MISSING_LINUX_DISPLAY_MESSAGE).toContain('`xorg-x11-server-Xvfb`')
})
it('starts Xvfb when the configured local display is stale', async () => {
it('leaves an externally configured stale display untouched', async () => {
setPlatform('linux')
process.env.DISPLAY = ':77'
spawnSyncMock.mockReturnValue({ status: 0 }) // `which Xvfb` succeeds
// First existsSync (stale-socket check) false; later (socket-ready poll) true.
existsSyncMock.mockReturnValueOnce(false).mockReturnValue(true)
spawnMock.mockReturnValue({ once: vi.fn(), kill: vi.fn(), killed: false })
const processOnceSpy = vi.spyOn(process, 'once')
const processRemoveListenerSpy = vi.spyOn(process, 'removeListener')
const { ensureVirtualDisplayForHeadlessServe, stopVirtualDisplay } =
await import('./ensure-virtual-display')
statSyncMock.mockReturnValue({ isSocket: () => true })
existsSyncMock.mockReturnValue(true)
readFileSyncMock.mockImplementation(() => {
throw new Error('display lock is outside this namespace')
})
const { ensureVirtualDisplayForHeadlessServe } = await import('./ensure-virtual-display')
expect(ensureVirtualDisplayForHeadlessServe({ isServeMode: true })).toBe(true)
expect(spawnMock).toHaveBeenCalledWith(
'Xvfb',
expect.arrayContaining([':99', '-terminate']),
expect.objectContaining({ detached: true })
)
expect(process.env.DISPLAY).toBe(':99')
expect(appMock.disableHardwareAcceleration).toHaveBeenCalled()
expect(appMock.commandLine.appendSwitch).toHaveBeenCalledWith('disable-dev-shm-usage')
expect(appMock.commandLine.appendSwitch).toHaveBeenCalledWith('disable-gpu')
expect(processOnceSpy).toHaveBeenCalledWith('exit', stopVirtualDisplay)
const readyHandler = appMock.once.mock.calls.find(([event]) => event === 'ready')?.[1]
expect(readyHandler).toBeTypeOf('function')
readyHandler()
expect(processRemoveListenerSpy).toHaveBeenCalledWith('exit', stopVirtualDisplay)
expect(appMock.once.mock.calls.some(([event]) => event === 'will-quit')).toBe(false)
expect(ensureVirtualDisplayForHeadlessServe({ isServeMode: true })).toBe(false)
expect(spawnSyncMock).not.toHaveBeenCalled()
expect(spawnMock).not.toHaveBeenCalled()
expect(rmSyncMock).not.toHaveBeenCalled()
expect(process.env.DISPLAY).toBe(':77')
})
it('reuses an existing virtual display only when its X server is alive', async () => {
+12 -2
View File
@@ -174,8 +174,18 @@ export function ensureVirtualDisplayForHeadlessServe(options: { isServeMode: boo
configureHeadlessServeChromiumFlags()
// Offscreen serve windows require X11; Wayland alone still needs Xvfb.
if (hasUsableXDisplay(process.env.DISPLAY)) {
return true
// Never delete artifacts from an externally managed display: a container may
// expose its socket without the host lock/PID being visible here.
const configuredDisplay = process.env.DISPLAY?.trim()
if (configuredDisplay) {
if (hasUsableXDisplay(configuredDisplay)) {
return true
}
console.warn(
`[serve] DISPLAY=${configuredDisplay} is not verifiably live; leaving it untouched. ` +
'Unset DISPLAY to let Orca start its own Xvfb.'
)
return false
}
if (!hasXvfbBinary()) {