fix(core): harden PTY resize against native crashes (#27496)

This commit is contained in:
Tommaso Sciortino
2026-05-28 09:16:24 -07:00
committed by GitHub
parent 5cac7c10fa
commit bd53951dc8
2 changed files with 40 additions and 22 deletions
+5 -2
View File
@@ -21,9 +21,12 @@ import {
// Tracking bug: https://github.com/microsoft/node-pty/issues/827 // Tracking bug: https://github.com/microsoft/node-pty/issues/827
process.on('uncaughtException', (error) => { process.on('uncaughtException', (error) => {
if (error instanceof Error) { if (error instanceof Error) {
const message = error.message || '';
const isPtyResizeError = const isPtyResizeError =
error.message === 'Cannot resize a pty that has already exited'; message === 'Cannot resize a pty that has already exited';
const isEbadfError = error.message.includes('EBADF'); const isEbadfError =
message.includes('EBADF') ||
(error as { code?: string }).code === 'EBADF';
const isFromNodePty = const isFromNodePty =
error.stack?.includes('node-pty') || error.stack?.includes('PtyResize'); error.stack?.includes('node-pty') || error.stack?.includes('PtyResize');
@@ -37,6 +37,7 @@ import {
} from './sandboxManager.js'; } from './sandboxManager.js';
import type { SandboxConfig } from '../config/config.js'; import type { SandboxConfig } from '../config/config.js';
import { killProcessGroup } from '../utils/process-utils.js'; import { killProcessGroup } from '../utils/process-utils.js';
import { isNodeError } from '../utils/errors.js';
import { import {
ExecutionLifecycleService, ExecutionLifecycleService,
type ExecutionHandle, type ExecutionHandle,
@@ -1507,7 +1508,22 @@ export class ShellExecutionService {
} }
const activePty = this.activePtys.get(pid); const activePty = this.activePtys.get(pid);
if (activePty) { if (!activePty) {
return;
}
// Skip Windows: process.kill(pid, 0) is heavy and native errors are catchable there.
if (process.platform !== 'win32') {
try {
process.kill(pid, 0);
} catch (e) {
// Bail only if the process is explicitly confirmed dead (ESRCH).
if (isNodeError(e) && e.code === 'ESRCH') {
return;
}
}
}
try { try {
activePty.ptyProcess.resize(cols, rows); activePty.ptyProcess.resize(cols, rows);
activePty.headlessTerminal.resize(cols, rows); activePty.headlessTerminal.resize(cols, rows);
@@ -1530,7 +1546,6 @@ export class ShellExecutionService {
throw e; throw e;
} }
} }
}
// Force emit the new state after resize // Force emit the new state after resize
if (activePty) { if (activePty) {