mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-05-05 23:42:03 +00:00
fix: prevent AbortSignal listener memory leak
- Add abort listener cleanup in Query.close() to prevent memory leak - Add abort listener cleanup in ControlDispatcher.shutdown() - Remove AbortController recreation in Session.handleInterrupt() This fixes the MaxListenersExceededWarning that occurred when: - Creating 11+ Query instances in SDK/non-interactive mode - Multiple user interrupts (Ctrl+C) in interactive mode - Intensive control request scenarios
This commit is contained in:
parent
66f754e203
commit
3f04217458
3 changed files with 26 additions and 5 deletions
|
|
@ -80,6 +80,8 @@ export class ControlDispatcher implements IPendingRequestRegistry {
|
|||
private pendingOutgoingRequests: Map<string, PendingOutgoingRequest> =
|
||||
new Map();
|
||||
|
||||
private abortHandler: (() => void) | null = null;
|
||||
|
||||
constructor(context: IControlContext) {
|
||||
this.context = context;
|
||||
|
||||
|
|
@ -102,9 +104,10 @@ export class ControlDispatcher implements IPendingRequestRegistry {
|
|||
// this.hookController = new HookController(context, this, 'HookController');
|
||||
|
||||
// Listen for main abort signal
|
||||
this.context.abortSignal.addEventListener('abort', () => {
|
||||
this.abortHandler = () => {
|
||||
this.shutdown();
|
||||
});
|
||||
};
|
||||
this.context.abortSignal.addEventListener('abort', this.abortHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -240,6 +243,12 @@ export class ControlDispatcher implements IPendingRequestRegistry {
|
|||
shutdown(): void {
|
||||
debugLogger.debug('[ControlDispatcher] Shutting down');
|
||||
|
||||
// Remove abort listener to prevent memory leak
|
||||
if (this.abortHandler) {
|
||||
this.context.abortSignal.removeEventListener('abort', this.abortHandler);
|
||||
this.abortHandler = null;
|
||||
}
|
||||
|
||||
// Cancel all incoming requests
|
||||
for (const [
|
||||
_requestId,
|
||||
|
|
|
|||
|
|
@ -408,7 +408,8 @@ class Session {
|
|||
private handleInterrupt(): void {
|
||||
debugLogger.info('[Session] Interrupt requested');
|
||||
this.abortController.abort();
|
||||
this.abortController = new AbortController();
|
||||
// Do not create a new AbortController to prevent listener leaks.
|
||||
// Subsequent queries will check signal.aborted and fail immediately.
|
||||
}
|
||||
|
||||
private setupSignalHandlers(): void {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue