google-gemini / google-gemini/gemini-cli

Temporary Directory Leak During Background Shell Execution

Open
#28,392 3 comments 0 reactions 0 assignees View on GitHub
area/core effort/medium kind/bug priority/p1 status/bot-triaged
Dominant language
TypeScript
Stars
107k
Forks
14.6k
Avg merge
2d 3h
Merged PRs (30d)
45

Description

# 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:

```ts
// 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:

```ts
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.

Contributor guide

Open the contributing guide

Research direction

Start in packages/core/src/tools/shell.ts and packages/core/src/services/ShellExecutionService.ts, tracing how the temporary directory is created and how background process completion is handled. Pass ownership of the directory to the background execution path, then add an integration test that runs a short-lived background command and verifies the directory is deleted without changing foreground cleanup.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.