Request signal isn't aborted after garbage collection
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 122k
- Forks
- 37.3k
- Avg merge
- 4d 2h
- Merged PRs (30d)
- 283
Description
Bug Description
Passing a signal to Request() and aborting it does not cause the underlying request signal to be aborted after it's been garbage collected. This leads to issues where you want to listen on the request signal even after the request itself falls out of scope - e.g., the request is instantiated with an abort controller signal and downstream code is waiting for that signal to be aborted via request.signal.
Reproducible By
Run the following using node --expose-gc main.js:
const ac = new AbortController();
ac.signal.addEventListener("abort", () => {
console.log("ac signal aborted");
});
const request = new Request("https://google.ca", { signal: ac.signal });
request.signal.addEventListener("abort", () => {
console.log("request signal aborted");
});
setTimeout(() => {
global.gc();
ac.abort();
}, 0);
Expected Behavior
ac signal aborted and request signal aborted should be logged to the console.
Instead, only ac signal aborted is logged.
Environment
Latest node and undici. Tried it in some older versions as well.
Additional context
A few folks are running into this while trying to close event stream requests in the remix web framework. The underlying requests are never closed because the signal doesn't get aborted.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the provided main.js reproduction with node --expose-gc, then trace Request(), request.signal, and AbortController signal propagation through the relevant Node.js implementation. Done means both “ac signal aborted” and “request signal aborted” are logged after garbage collection and aborting the controller, with coverage for the reproduced case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, nodejs
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100