Repository navigation
AbortSignal.any() leaks when any of the provided signal is long-lived #55351
Description
Activity
- addedabortcontrollerIssues and PRs related to the AbortController and AbortSignal APIs.Issues and PRs related to the AbortController and AbortSignal APIs.and removed
on Oct 10, 2024 Hm, the memory is being allocated just for refs - potentially pointing to nothing?
Something like this would work?
const finalizers = new SafeFinalizationRegistry((signal) => { signal[kDependantSignals].forEach(ref => { if (!ref.deref()) { signal[kDependantSignals].delete(ref); } }); });
Then in the loop having this
// ... for (let i = 0; i < signalsArray.length; i++) { const signal = signalsArray[I]; finalizers.register(resultSignal, signal); // ...
Executing this repro after this (maybe naive?) change
./node test.js 100000 - 102.05 MiB - 29116 signals 200000 - 110.38 MiB - 26503 signals 300000 - 110.88 MiB - 21856 signals 400000 - 110.95 MiB - 17219 signals 500000 - 110.41 MiB - 12624 signals 600000 - 110.17 MiB - 8016 signals 700000 - 110.00 MiB - 3414 signals 800000 - 112.42 MiB - 33650 signals 900000 - 111.17 MiB - 29002 signals 1000000 - 111.22 MiB - 24377 signals 1100000 - 111.31 MiB - 19735 signals 1200000 - 110.69 MiB - 15108 signals 1300000 - 110.69 MiB - 10480 signals 1400000 - 110.50 MiB - 5784 signals 1500000 - 110.33 MiB - 1181 signals 1600000 - 111.47 MiB - 31432 signals 1700000 - 112.11 MiB - 26792 signals 1800000 - 112.16 MiB - 22141 signals 1900000 - 112.17 MiB - 17532 signals 2000000 - 111.53 MiB - 12900 signals 2100000 - 111.53 MiB - 8255 signals 2200000 - 111.08 MiB - 3607 signals 2300000 - 113.48 MiB - 33826 signals 2400000 - 112.30 MiB - 29157 signals 2500000 - 112.30 MiB - 24488 signals 2600000 - 112.30 MiB - 19846 signals 2700000 - 111.75 MiB - 15259 signals 2800000 - 111.77 MiB - 10527 signals 2900000 - 111.44 MiB - 5933 signals 3000000 - 111.28 MiB - 1325 signalsRef: chromium/chromium@d5b7539 - I think it would be the "settled" case(?)
Is anyone working on this issue?
- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.
on Oct 13, 2024 Can confirm that we have a problem on this, however, it is not
AbortSignalinstances that are being leaked, it'sWeakRefs. Specifically, the set of dependent signals known to theAbortSignalare kept in an internalSetusingWeakRefs. TheAbortSignals are being properly gc'd but theSetis never cleaned out of theWeakRefs making those leak.Is anyone working on this issue?
I have a pr opened to address this issue.
Reacted by Aviv Keller and Toni VillenaIs anyone working on this issue?
I have a pr opened to address this issue.
So if I want to work on this issue do I need to contact someone or I can start working right away?
Is anyone working on this issue?
I have a pr opened to address this issue.
So if I want to work on this issue do I need to contact someone or I can start working right away?@siddhant0410 The PR here #55354 by @geeksilva97 already fixes this issue, so there's nothing else to do here but wait for the PR to be merged and backported.
Is anyone working on this issue?
I have a pr opened to address this issue.
So if I want to work on this issue do I need to contact someone or I can start working right away?@siddhant0410 The PR here #55354 by @geeksilva97 already fixes this issue, so there's nothing else to do here but wait for the PR to be merged and backported.
Thanks for the update!
- added a commit that references this issue
on Apr 23, 2026 - added a commit that references this issue
on Apr 23, 2026 - added a commit that references this issue
on May 1, 2026
Version
v22.9.0
Platform
Subsystem
No response
What steps will reproduce the bug?
How often does it reproduce? Is there a required condition?
Always
What is the expected behavior? Why is that the expected behavior?
AbortSignal.any should not case memory leaks
What do you see instead?
Additional information
It's pretty clear that
AbortSignal.anyattaches the combined signal to all its parent signals. But it only gets removed if the parent signals are actually aborted. If there is a long living signal among the parents, for instance something like a SIGINT handler, then it keeps accumulating WeakRefs to no longer existingAbortSignals.Related issues:
AbortSignalreturned byAbortSignal.any