Skip to content

Conversation

galz10
Copy link
Collaborator

@galz10 galz10 commented Oct 6, 2025

TLDR

This pull request improves the reliability of the ShellExecutionService by implementing a graceful shutdown sequence for aborted commands, preventing the CLI from hanging on abortion, and capping memory usage to avoid crashes with high-output commands.

Dive Deeper

This commit enhances the ShellExecutionService with several key improvements:

  • Graceful Shutdown: Implements a graceful shutdown sequence on command abortion, sending SIGTERM followed by SIGKILL to allow processes to terminate cleanly.
  • Immediate Promise Resolution: Ensures immediate promise resolution upon abortion, preventing the CLI from hanging while processing buffered output.
  • Memory Capping: Introduces a sliding window buffer for the child_process fallback to cap memory usage at 16MB for stdout and stderr, preventing potential crashes with high-output commands.
  • Refined Rendering: Refines rendering logic to ensure timely and accurate updates.

These changes make the shell execution more robust and prevent common issues related to process management and memory consumption.

Reviewer Test Plan

  1. Test Graceful Shutdown & No Hanging:

    • Run a long-running command (e.g., sleep 10).
    • Abort the command (e.g., with Ctrl+C).
    • Expected: The CLI should immediately become responsive, and the sleep process should be terminated. You can verify with ps aux | grep sleep.
  2. Test High-Output Command (Memory Capping):

    • Run a command that produces a large amount of output (e.g., yes | head -n 1000000).
    • Expected: The CLI should handle the output without crashing or consuming excessive memory. The output in the CLI might be truncated, which is expected.
  3. Test Aborting a High-Output Command:

    • Run a command that continuously produces output (e.g., yes).
    • Abort the command.
    • Expected: The CLI should stop the command and return to a responsive state without any delay or hanging.

Testing Matrix

🍏 🪟 🐧
npm run
npx
Docker
Podman - -
Seatbelt - -

Linked issues / bugs

  This commit enhances the ShellExecutionService with several key improvements:

   - Implements a graceful shutdown sequence on command abortion, sending SIGTERM followed by SIGKILL to allow processes to terminate cleanly.
   - Ensures immediate promise resolution upon abortion, preventing the CLI from hanging while processing buffered output.
   - Introduces a sliding window buffer for the child_process fallback to cap memory usage at 16MB for stdout and stderr, preventing potential
     crashes with high-output commands.
   - Refines rendering logic to ensure timely and accurate updates.
@galz10 galz10 requested a review from a team as a code owner October 6, 2025 17:49
Copy link
Contributor

Summary of Changes

Hello @galz10, 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 significantly enhances the robustness and reliability of the ShellExecutionService. It addresses issues related to command abortion by implementing a graceful shutdown mechanism and ensuring immediate responsiveness of the CLI. Furthermore, it prevents potential crashes caused by excessive memory consumption during high-output commands by introducing a memory cap for buffered output.

Highlights

  • Graceful Shutdown: Implemented a graceful shutdown sequence for aborted commands, using SIGTERM followed by SIGKILL to ensure clean termination and prevent processes from lingering.
  • Immediate Abort Resolution: Ensures that promises resolve immediately upon command abortion, preventing the CLI from hanging even when processing large buffered output.
  • Memory Capping: Introduced a 16MB sliding window buffer for stdout and stderr in the child_process fallback, preventing memory exhaustion and crashes for commands producing high volumes of output.
  • Refined Rendering: Improved the rendering logic for terminal output to ensure more timely and accurate updates.
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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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
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 significantly improves the robustness of the ShellExecutionService. The changes introduce a graceful shutdown mechanism (SIGTERM followed by SIGKILL), prevent the CLI from hanging on abort by resolving promises immediately, and cap memory usage for the child_process fallback to avoid crashes. The tests have been updated accordingly to cover these new behaviors. My review focuses on ensuring the new shutdown logic is fully robust against race conditions that could lead to unhandled errors.

Copy link

github-actions bot commented Oct 6, 2025

Size Change: +3.08 kB (+0.02%)

Total Size: 17.8 MB

Filename Size Change
./bundle/gemini.js 17.8 MB +3.08 kB (+0.02%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-closed.sb 1.03 kB
./bundle/sandbox-macos-permissive-open.sb 830 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-closed.sb 3.29 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB

compressed-size-action

const { Terminal } = pkg;

const SIGKILL_TIMEOUT_MS = 200;
const MAX_CHILD_PROCESS_BUFFER_SIZE = 16 * 1024 * 1024; // 16MB
Copy link
Collaborator

Choose a reason for hiding this comment

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

can you comment on why 16MB?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Figured we want to limit the size of the buffer so that it doesn't crash the cli , 16mb is ~3-5 millions lines of text .

@galz10 galz10 requested a review from jacob314 October 6, 2025 19:19
@jacob314 jacob314 requested a review from abhipatel12 October 6, 2025 19:59

if (stream === 'stdout') {
stdout += decodedChunk;
if (stdout.length > MAX_CHILD_PROCESS_BUFFER_SIZE) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

we should notify the user&model if there is truncation. also consider making a helper method that safely appends content to the buffer truncating as needed. This logic is fine in general but would have edge case issues if stdout + decodedChunk was large enough to exceed the maximum string size we can handle. It would be instead by slightly more performance and robust to first truncate stdout by the amount needed to fit within the buffer size and only then add decodedChunk. For full robustness would also need to handle if decodedChunk is larger than MAX_CHILD_PROCESS_BUFFER_SIZE

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added this

image

not sure if i should actually make it a warning/notification message that shows up as yellow.

galz10 added 7 commits October 7, 2025 11:10
   warning

   This commit refactors the shell execution service's
   `child_process` fallback to improve how large outputs are
   handled.

   Key changes:
   - Implements a sliding window for stdout and stderr buffers.
   This ensures that if the output exceeds the 16MB limit, the
   most recent content is preserved, rather than just truncating
   the end.
   - Appends a clear warning message to the output when
   truncation occurs, informing the user that the output has been
   shortened.
   - Strengthens the associated tests, removing reliance on fake
   timers for abort scenarios and verifying the new truncation
   behavior and warning message.
   When running shell commands that produce a large volume of rapid output, the UI would
   appear to freeze, only rendering the output upon cancellation or completion.

   This was due to the PTY rendering logic using a debounce mechanism, which was continuously
   reset by the high-frequency data stream, preventing the UI from updating.

   This commit replaces the debounced rendering with a throttled approach in
   `shellExecutionService.ts`. The UI is now guaranteed to render updates at a regular
   interval (every 17ms), ensuring responsiveness even during stdout floods.

   The redundant client-side throttling in `shellCommandProcessor.ts` has been removed to rely
   solely on the new, more efficient core implementation.
@galz10 galz10 requested a review from jacob314 October 8, 2025 21:40
galz10 added 5 commits October 8, 2025 14:40
  Previously, a race condition could occur where a user could not cancel a shell command. If the command's process exited but was still streaming a large amount of output, the cancellation
  signal would be ignored while the output processing completed, causing the CLI to hang.

  This change introduces a Promise.race in the onExit handler. It races the output processing promise against a promise that resolves on cancellation. This ensures that an abort signal is
  respected immediately, even during the final output processing phase, making command cancellation robust and preventing the application from becoming unresponsive.
Copy link
Collaborator

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

@galz10 galz10 enabled auto-merge October 10, 2025 22:07
@galz10 galz10 added this pull request to the merge queue Oct 10, 2025
Merged via the queue into main with commit 265d39f Oct 10, 2025
20 checks passed
@galz10 galz10 deleted the galzahavi/fix/shell-output branch October 10, 2025 22:22
thacio added a commit to thacio/auditaria that referenced this pull request Oct 13, 2025
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.

RangeError: Invalid string length (Crash) when running commands with large stdout output

2 participants