Skip to content

fix(core): make shell tool work under Bun - #3

Closed
euxaristia wants to merge 1 commit into
mainfrom
fix/bun-pty-fallback-and-resize-ebadf
Closed

fix(core): make shell tool work under Bun#3
euxaristia wants to merge 1 commit into
mainfrom
fix/bun-pty-fallback-and-resize-ebadf

Conversation

@euxaristia

Copy link
Copy Markdown
Owner

Summary

Two related runtime issues prevented bun-launched builds of gemini-cli from running shell tool calls. The first failure visible to a user is an ioctl(2) failed, EBADF crash inside a React useEffect. After patching that, the shell tool stops crashing but every command returns empty output. Both stem from @lydell/node-pty not behaving correctly when loaded by Bun.

  • No output under Bun. getPty() now short-circuits to the existing child_process fallback when process.versions.bun is set. The fallback path already has Bun-specific handling (detached:false to avoid immediate SIGHUP, added in fix(core): disable detached mode in Bun to prevent immediate SIGHUP of child processes google-gemini/gemini-cli#22620). GEMINI_PTY_INFO=node-pty overrides the new behavior for anyone wanting to test the pty path under Bun.
  • ioctl(2) failed, EBADF crash on resize. ShellExecutionService.onExit calls destroyPtyProcess() (which closes the master fd) before the entry is removed from activePtys at the end of the cleanupLogStream promise chain. A concurrent resizePty() from ShellToolMessage's useEffect lands in that window, calls the native resize on a closed fd, and ioctl returns EBADF. The window is narrow under Node but widens under Bun's microtask scheduling. resizePty() now treats EBADF/ENOTTY the same way it already treats ESRCH and the Windows "Cannot resize a pty that has already exited" message — the pty is gone, nothing to resize.

The two fixes are independent but both required: the fallback gating prevents the bad state from being entered under Bun, the resize guard makes the race safe everywhere in case a stray pty path is hit (manual GEMINI_PTY_INFO=node-pty testing, future runtimes with similar timing).

Test plan

  • bun start no longer crashes with ioctl(2) failed, EBADF on shell tool calls
  • Shell tool calls under bun start produce captured output (e.g. echo hello, bun --version, which bun)
  • Existing behavior unchanged under Node: pty path still selected, no new code runs on the hot path
  • GEMINI_PTY_INFO=node-pty bun start re-enables the pty path (still broken under Bun, but useful for confirming the override works)
  • New unit test should ignore EBADF when the master fd was already closed covers the resize swallow

🤖 Generated with Claude Code

Two related runtime issues prevented `bun start`/`bun`-launched builds of
gemini-cli from running shell tool calls:

1. The pty path silently captures no output under Bun — node-pty's
   `tty.ReadStream` wrapper around the master fd doesn't deliver data to
   `onData`, so the shell tool reports success with an empty result.
2. When `resizePty` does run, it hits `ioctl(2) failed, EBADF` because
   `destroyPtyProcess()` in `onExit` closes the master fd before the entry
   is removed from `activePtys`. The window is narrow on Node but widens
   under Bun's microtask scheduling, crashing the React render.

getPty() now short-circuits to the existing `child_process` fallback when
running under Bun (which already has Bun-specific `detached:false`
handling). `GEMINI_PTY_INFO=node-pty` overrides for testing.

resizePty() also swallows the `EBADF`/`ENOTTY` ioctl errors the same way
it already swallows `ESRCH` and the Windows "already exited" message —
they all mean the same thing: the pty is gone, nothing to resize.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@gemini-code-assist

Copy link
Copy Markdown

Warning

Gemini encountered an error creating the summary. You can try again by commenting /gemini summary.

@euxaristia euxaristia closed this May 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant