nodejs / nodejs/node

Request signal isn't aborted after garbage collection

Open
#55,428 13 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

confirmed-bug
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.