Google Gemini CLI — Fixing Stream Cancellation & Memory Leaks (PR #20778)
Traced and resolved an asynchronous stream cancellation flaw in Google's official google-gemini/gemini-cli repository, threading AbortSignal through multi-turn compression pipelines.
100%
Merged by Google Team
0 Leaks
Detached Promises Fixed
TypeScript
Async Architecture
Core Fix
AbortSignal Propagation
1. The Problem: Detached In-Flight LLM Invocations
In multi-turn terminal chat sessions with Gemini, pressing Ctrl+C or issuing an abort command cancelled the active UI stream, but failed to cancel the background chat history compression service.
Because the compression routine was invoked on a detached promise chain without receiving the active turn's AbortSignal, background network requests continued executing against Google Cloud APIs — causing billing spikes, memory leaks, and race conditions on subsequent prompt dispatches.
2. The Solution: End-to-End AbortSignal Threading
I refactored the execution pipeline across LocalAgentExecutor, GeminiClient, and the ChatCompressionService:
// Refactored async execution boundary with AbortSignal threading
async executeTurn(prompt: string, options: { signal?: AbortSignal }) {
const { signal } = options;
// Guaranteed signal propagation through compression middleware
if (this.shouldCompressHistory()) {
await this.compressionService.compress({
history: this.chatHistory,
signal, // Propagated abort controller
});
}
return this.client.streamGenerateContent(prompt, { signal });
}- Graceful Cleanup: Guaranteed that all HTTP sockets and background workers terminate immediately upon user cancellation.
- Deterministic State: Eliminated out-of-order history compression race conditions when rapid consecutive prompts are entered.
3. Code Review & Upstream Merge
The pull request underwent review by Google engineers, verified with unit test suites and integration tests across Linux, macOS, and Windows runtime environments, and was merged into main.