Skip to content

fix(core): use close event instead of exit in child_process fallback#25695

Merged
scidomino merged 2 commits intogoogle-gemini:mainfrom
tusaryan:fix-shell-command-output-race
May 4, 2026
Merged

fix(core): use close event instead of exit in child_process fallback#25695
scidomino merged 2 commits intogoogle-gemini:mainfrom
tusaryan:fix-shell-command-output-race

Conversation

@tusaryan
Copy link
Copy Markdown
Contributor

Summary

Switch child.on('exit') to child.on('close') in childProcessFallback() to fix stdout being lost on fast commands.

Details

  • child.on('exit')child.on('close') in childProcessFallback()
  • Tests updated to emit close after exit (matching real Node.js behavior)
  • PTY path unaffected

Related Issues

Fixes #24923

How to Validate

  1. npm test -w @google/gemini-cli-core -- src/services/shellExecutionService.test.ts
  2. npm run preflight

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • Noted breaking changes (if any)
  • Validated on required platforms/methods:
    • MacOS
      • npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

…oogle-gemini#24923)

Switch ShellExecutionService to listen for the child process 'close' event instead of 'exit' so exit handling occurs after stdio streams are closed. Update unit tests to emit the 'close' event in the mocked child processes to match the new behavior. Modified files: packages/core/src/services/shellExecutionService.ts and packages/core/src/services/shellExecutionService.test.ts.
@tusaryan tusaryan requested a review from a team as a code owner April 20, 2026 10:29
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses an issue where stdout could be lost during the execution of fast commands. By switching the event listener from 'exit' to 'close', the service now correctly waits for the process streams to be fully closed before finalizing the execution result. The changes also include necessary updates to the test suite to ensure that mock child processes simulate the standard Node.js lifecycle events correctly.

Highlights

  • Event Listener Update: Changed the child process event listener from 'exit' to 'close' in the shell execution service to ensure proper handling of command output.
  • Test Suite Alignment: Updated multiple test cases to emit the 'close' event after 'exit', accurately reflecting Node.js child process behavior.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the ShellExecutionService to listen for the close event instead of the exit event when executing child processes, ensuring that all stdio streams are fully drained before resolving. Corresponding updates were made to the test suite to emit the close event in mock child processes. However, switching to close may cause the CLI to hang if a command spawns a long-lived background process that keeps the stdout/stderr pipes open, which could be a significant regression for a terminal-first tool.

Comment on lines +775 to 777
child.on('close', (code, signal) => {
handleExit(code, signal);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Switching from the exit event to the close event is a common fix for ensuring all buffered stdout/stderr data is captured, especially for fast-running commands. However, this change introduces a potential regression: the close event waits for all stdio streams to be closed. If the child process spawns a long-lived background process (e.g., command &) that inherits the stdout/stderr pipes and does not close them, the close event will not fire until that background process terminates. This can cause the CLI to hang indefinitely or appear unresponsive for commands that have technically finished their primary execution.

Since this is a terminal-first tool, this hang could be a significant UX issue. Consider if a hybrid approach (e.g., listening to exit but waiting for a short timeout or for the end event on individual streams) might be more robust, or at least document this as a known limitation for backgrounded processes in the fallback path.

Copy link
Copy Markdown
Contributor Author

@tusaryan tusaryan Apr 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gemini-code-assist The hanging scenario shouldn't be an issue here. the shell tool already has an inactivity timeout that kills the entire process group (including grandchildren) if nothing is produced. Background commands also return early via is_background without blocking.

close is the standard way to handle this per Node.js docs: https://nodejs.org/docs/latest-v20.x/api/child_process.html#event-close

@tusaryan
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the ShellExecutionService to listen for the 'close' event instead of the 'exit' event when a child process terminates. This change ensures that all stdio streams are fully closed before the exit handler is executed, providing more reliable output handling. Corresponding updates were made to the test suite to simulate the 'close' event in various execution scenarios. I have no feedback to provide.

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/core Issues related to User Interface, OS Support, Core Functionality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! labels Apr 20, 2026
@scidomino scidomino enabled auto-merge April 30, 2026 20:36
@scidomino scidomino added this pull request to the merge queue May 4, 2026
Merged via the queue into google-gemini:main with commit d313cd7 May 4, 2026
27 checks passed
TirthNaik-99 pushed a commit to TirthNaik-99/gemini-cli that referenced this pull request May 4, 2026
kimjune01 pushed a commit to kimjune01/gemini-cli-claude that referenced this pull request May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/core Issues related to User Interface, OS Support, Core Functionality help wanted We will accept PRs from all issues marked as "help wanted". Thanks for your support! priority/p2 Important but can be addressed in a future release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

run_shell_command: stdout lost on fast commands due to child.on('exit') vs child.on('close') race in shellExecutionService

2 participants