Skip to content

Temporary Directory Leak During Background Shell Execution #28392

Description

@Daksh7785

Reliability: Temporary directory leak for background shell executions

Category: Reliability / Resource Leak
Priority: High

Affected Components

  • packages/core/src/tools/shell.ts
  • packages/core/src/services/ShellExecutionService.ts

Summary

When a shell command is executed with is_background: true, the CLI creates a temporary directory (gemini-shell-*) to store bgpids.tmp. This directory is never removed after the background task finishes, resulting in a permanent resource leak.

Over time, repeated background executions accumulate orphaned directories inside the system temporary folder.

Current Behavior

The shell tool creates a temporary directory using fs.mkdtempSync() before executing the command.

For foreground commands, the directory is removed in the finally block.

For background commands, cleanup is intentionally skipped:

// Only clean up if NOT running in background.
if (!this.params.is_background) {
  // cleanup...
}

However, ownership of this temporary directory is never transferred to ShellExecutionService, so nothing removes it after the background process exits.

Expected Behavior

The temporary directory should be automatically deleted once the background process has completed.

Steps to Reproduce

  1. Run any background command (e.g., sleep 10) with is_background: true.
  2. Inspect the system temp directory (/tmp or %TEMP%).
  3. Observe a new gemini-shell-* directory.
  4. Wait for the background process to finish.
  5. The directory still exists.

Impact

  • Temporary directories accumulate indefinitely.
  • Long-running CLI sessions or A2A server mode may create thousands of orphaned directories.
  • Can eventually consume temporary storage or available inodes, leading to ENOSPC errors.

Suggested Solution

Transfer ownership of the temporary directory to ShellExecutionService.

A minimal approach would be to:

  • Extend ShellExecutionService.background(...) to accept the tempDir path.
  • Store the directory alongside the background process metadata.
  • Remove the directory when the background process exits using:
await fsPromises.rm(tempDir, {
  recursive: true,
  force: true,
});

This keeps the existing behavior unchanged while ensuring temporary resources are cleaned up after the background task completes.

Testing

Add an integration test that:

  1. Starts a short-lived background command.
  2. Waits for it to exit.
  3. Verifies the temporary directory has been deleted.

Acceptance Criteria

  • ShellExecutionService accepts ownership of the temporary directory.
  • Temporary directory is deleted when the background process exits.
  • Integration test verifies cleanup.
  • No behavior change for foreground shell execution.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/coreIssues related to User Interface, OS Support, Core Functionalityeffort/medium2-3 days: UI state, async flow, cross-component refactorsstatus/bot-triaged

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions