diff --git a/src/conpty_console_list_agent.test.ts b/src/conpty_console_list_agent.test.ts new file mode 100644 index 00000000..daaf8f04 --- /dev/null +++ b/src/conpty_console_list_agent.test.ts @@ -0,0 +1,31 @@ +/** + * Copyright (c) 2024, Microsoft Corporation (MIT License). + */ + +import * as assert from 'assert'; +import * as path from 'path'; +import { fork } from 'child_process'; + +if (process.platform === 'win32') { + describe('conpty_console_list_agent', () => { + it('should gracefully handle AttachConsole failure for a dead PID', (done) => { + const agentPath = path.join(__dirname, 'conpty_console_list_agent'); + const deadPid = 999999; + + const agent = fork(agentPath, [deadPid.toString()]); + + agent.on('message', (message: { consoleProcessList: number[] }) => { + // When AttachConsole fails, the agent should fall back to returning + // just the shell PID rather than crashing. + assert.deepStrictEqual(message.consoleProcessList, [deadPid]); + done(); + }); + + agent.on('exit', (code) => { + if (code !== 0) { + done(new Error(`Agent exited with code ${code}, expected graceful fallback`)); + } + }); + }); + }); +} diff --git a/src/conpty_console_list_agent.ts b/src/conpty_console_list_agent.ts index 181ccabb..76ffa285 100644 --- a/src/conpty_console_list_agent.ts +++ b/src/conpty_console_list_agent.ts @@ -10,6 +10,13 @@ import { loadNativeModule } from './utils'; const getConsoleProcessList = loadNativeModule('conpty_console_list').module.getConsoleProcessList; const shellPid = parseInt(process.argv[2], 10); -const consoleProcessList = getConsoleProcessList(shellPid); -process.send!({ consoleProcessList }); +try { + const consoleProcessList = getConsoleProcessList(shellPid); + process.send!({ consoleProcessList }); +} catch { + // AttachConsole can fail if the shell process has already exited. + // Fall back to returning just the shell PID, matching the timeout + // fallback behavior in windowsPtyAgent.ts. + process.send!({ consoleProcessList: [shellPid] }); +} process.exit(0);