fix: remove abort event listener from caller signal after request completes#1858
Open
xodn348 wants to merge 1 commit intoopenai:masterfrom
Open
fix: remove abort event listener from caller signal after request completes#1858xodn348 wants to merge 1 commit intoopenai:masterfrom
xodn348 wants to merge 1 commit intoopenai:masterfrom
Conversation
…pletes
When a caller passes a `signal` to `fetchWithTimeout`, the method adds an
abort listener on that signal to forward abort events to the internal
`AbortController`. Previously the listener was only cleaned up when the
signal fired (via `{ once: true }`), but was never removed on a successful
or failed request completion.
On Deno, `AbortSignal.timeout()` refs its underlying timer whenever a
listener is attached. The orphaned listener kept the timer alive for the
full timeout duration, preventing the process from exiting even after the
request returned successfully.
Fix by calling `signal.removeEventListener('abort', abort)` in the
`finally` block, mirroring the existing `clearTimeout` cleanup.
Fixes openai#1811
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1811.
When a caller passes a
signaltofetchWithTimeout, an abort listener is added on that signal to forward abort events to the internalAbortController. With{ once: true }, the listener cleans itself up when the signal fires — but if the request completes successfully (without the signal aborting), the listener is never removed.On Deno,
AbortSignal.timeout()refs its underlying timer whenever a listener is attached. The orphaned listener keeps the timer alive for the full timeout duration (e.g. 30 s), preventing the process from exiting even after the request returned in ~500 ms.Fix: call
signal.removeEventListener('abort', abort)in thefinallyblock, alongside the existingclearTimeout(timeout). This mirrors the symmetric cleanup already done for thesetTimeout.} finally { clearTimeout(timeout); + if (signal) signal.removeEventListener('abort', abort); }The
abortvariable is already a named reference (created bythis._makeAbort(controller)), so it can be passed to bothaddEventListenerandremoveEventListenerwithout any other changes.Test plan
removes abort listener from caller signal after successful request) that spies onaddEventListener/removeEventListenerof the caller's signal and asserts:{ once: true }removeEventListenerwas called with the same function reference after a successful fetchtests/index.test.tscontinue to pass (54/54)