Skip to content

Commit 73421e3

Browse files
fix(patch): cherry-pick bd53951 to release/v0.44.0-pr-27496 [CONFLICTS] (#27534)
Co-authored-by: Tommaso Sciortino <sciortino@gmail.com>
1 parent 1000b33 commit 73421e3

2 files changed

Lines changed: 49 additions & 26 deletions

File tree

packages/cli/index.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,21 @@ import {
2020
// Suppress known race condition error in node-pty on Windows
2121
// Tracking bug: https://github.com/microsoft/node-pty/issues/827
2222
process.on('uncaughtException', (error) => {
23-
if (
24-
process.platform === 'win32' &&
25-
error instanceof Error &&
26-
error.message === 'Cannot resize a pty that has already exited'
27-
) {
28-
// This error happens on Windows with node-pty when resizing a pty that has just exited.
29-
// It is a race condition in node-pty that we cannot prevent, so we silence it.
30-
return;
23+
if (error instanceof Error) {
24+
const message = error.message || '';
25+
const isPtyResizeError =
26+
message === 'Cannot resize a pty that has already exited';
27+
const isEbadfError =
28+
message.includes('EBADF') ||
29+
(error as { code?: string }).code === 'EBADF';
30+
const isFromNodePty =
31+
error.stack?.includes('node-pty') || error.stack?.includes('PtyResize');
32+
33+
if ((isPtyResizeError || isEbadfError) && isFromNodePty) {
34+
// This error happens with node-pty when resizing a pty that has just exited.
35+
// It is a race condition in node-pty that we cannot prevent, so we silence it.
36+
return;
37+
}
3138
}
3239

3340
// For other errors, we rely on the default behavior, but since we attached a listener,

packages/core/src/services/shellExecutionService.ts

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
} from './sandboxManager.js';
3939
import type { SandboxConfig } from '../config/config.js';
4040
import { killProcessGroup } from '../utils/process-utils.js';
41+
import { isNodeError } from '../utils/errors.js';
4142
import {
4243
ExecutionLifecycleService,
4344
type ExecutionHandle,
@@ -1541,30 +1542,45 @@ export class ShellExecutionService {
15411542
}
15421543

15431544
const activePty = this.activePtys.get(pid);
1544-
if (activePty) {
1545+
if (!activePty) {
1546+
return;
1547+
}
1548+
1549+
// Skip Windows: process.kill(pid, 0) is heavy and native errors are catchable there.
1550+
if (process.platform !== 'win32') {
15451551
try {
1546-
activePty.ptyProcess.resize(cols, rows);
1547-
activePty.headlessTerminal.resize(cols, rows);
1552+
process.kill(pid, 0);
15481553
} catch (e) {
1549-
// Ignore errors if the pty has already exited, which can happen
1550-
// due to a race condition between the exit event and this call.
1551-
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1552-
const err = e as { code?: string; message?: string };
1553-
const isEsrch = err.code === 'ESRCH';
1554-
const isWindowsPtyError = err.message?.includes(
1555-
'Cannot resize a pty that has already exited',
1556-
);
1557-
1558-
if (isEsrch || isWindowsPtyError) {
1559-
// On Unix, we get an ESRCH error.
1560-
// On Windows, we get a message-based error.
1561-
// In both cases, it's safe to ignore.
1562-
} else {
1563-
throw e;
1554+
// Bail only if the process is explicitly confirmed dead (ESRCH).
1555+
if (isNodeError(e) && e.code === 'ESRCH') {
1556+
return;
15641557
}
15651558
}
15661559
}
15671560

1561+
try {
1562+
activePty.ptyProcess.resize(cols, rows);
1563+
activePty.headlessTerminal.resize(cols, rows);
1564+
} catch (e) {
1565+
// Ignore errors if the pty has already exited, which can happen
1566+
// due to a race condition between the exit event and this call.
1567+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
1568+
const err = e as { code?: string; message?: string };
1569+
const isEsrch = err.code === 'ESRCH';
1570+
const isEbadf = err.code === 'EBADF' || err.message?.includes('EBADF');
1571+
const isWindowsPtyError = err.message?.includes(
1572+
'Cannot resize a pty that has already exited',
1573+
);
1574+
1575+
if (isEsrch || isEbadf || isWindowsPtyError) {
1576+
// On Unix, we get an ESRCH or EBADF error.
1577+
// On Windows, we get a message-based error.
1578+
// In both cases, it's safe to ignore.
1579+
} else {
1580+
throw e;
1581+
}
1582+
}
1583+
15681584
// Force emit the new state after resize
15691585
if (activePty) {
15701586
const endLine = activePty.headlessTerminal.buffer.active.length;

0 commit comments

Comments
 (0)