mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-22 02:54:31 -07:00
fix(core): clear 5-minute timeouts in oauth flow to prevent memory leaks (#24968)
This commit is contained in:
@@ -305,6 +305,28 @@ describe('oauth-flow', () => {
|
||||
'Invalid value for OAUTH_CALLBACK_PORT',
|
||||
);
|
||||
});
|
||||
|
||||
it('should settle on timeout without keeping the process alive', async () => {
|
||||
vi.useFakeTimers();
|
||||
try {
|
||||
const server = startCallbackServer('timeout-state');
|
||||
await server.port;
|
||||
|
||||
const responsePromise = server.response.catch((e: Error) => {
|
||||
if (e.message !== 'OAuth callback timeout') throw e;
|
||||
return e;
|
||||
});
|
||||
|
||||
// Advance timers by 5 minutes to trigger the timeout
|
||||
await vi.advanceTimersByTimeAsync(5 * 60 * 1000);
|
||||
|
||||
const error = await responsePromise;
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
expect((error as Error).message).toBe('OAuth callback timeout');
|
||||
} finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('exchangeCodeForToken', () => {
|
||||
|
||||
@@ -116,6 +116,8 @@ export function startCallbackServer(
|
||||
portReject = reject;
|
||||
});
|
||||
|
||||
let timeoutId: NodeJS.Timeout | undefined;
|
||||
|
||||
const responsePromise = new Promise<OAuthAuthorizationResponse>(
|
||||
(resolve, reject) => {
|
||||
let serverPort: number;
|
||||
@@ -221,18 +223,31 @@ export function startCallbackServer(
|
||||
portResolve(serverPort); // Resolve port promise immediately
|
||||
});
|
||||
|
||||
// Timeout after 5 minutes
|
||||
setTimeout(
|
||||
const abortController = new AbortController();
|
||||
timeoutId = setTimeout(
|
||||
() => {
|
||||
server.close();
|
||||
reject(new Error('OAuth callback timeout'));
|
||||
abortController.abort(new Error('OAuth callback timeout'));
|
||||
},
|
||||
5 * 60 * 1000,
|
||||
);
|
||||
timeoutId.unref();
|
||||
|
||||
const onAbort = () => {
|
||||
server.close();
|
||||
reject(abortController.signal.reason);
|
||||
};
|
||||
abortController.signal.addEventListener('abort', onAbort, { once: true });
|
||||
|
||||
server.on('close', () => {
|
||||
abortController.signal.removeEventListener('abort', onAbort);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return { port: portPromise, response: responsePromise };
|
||||
return {
|
||||
port: portPromise,
|
||||
response: responsePromise,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user