Memory leak in Promise.race/any with immediately-resolving promises requires investigation of Node.js internals.
The issue demonstrates a memory leak when using Promise.race or Promise.any with immediately-resolving promises in a loop. The problem appears specific to Node.js (not V8 alone) and requires understanding of async_hooks or promise implementation details. Maintainers have confirmed the bug but the root cause isn't yet identified.
21.5.0
Linux penguin 6.1.55-06877-gc83437f2949f #1 SMP PREEMPT_DYNAMIC Thu Dec 14 19:17:39 PST 2023 x86_64 GNU/Linux
async_hooks or async/await
Run the following code. Failure is quicker and less likely to interfere with system stability if you run with a low heap ceiling like this, but it will fail without...
node --max-old-space-size=16 test/examples/ephemeralPromiseMemoryLeak.js
//ephemeralPromiseMemoryLeak.js
async function promiseValue(value) {
return value;
}
async function run() {
for (;;) {
await Promise.race([promiseValue("foo"), promiseValue("bar")]);
}
}
run();
An equivalent OOM is created if you substitute Promise.any for Promise.race...
async function promiseValue(value) {
return value;
}
async function run() {
for (;;) {
await Promise.any([promiseValue("foo"), promiseValue("bar")]);
}
}
run();
It always fails.
I would expect it not to accumulate references in memory and fail.
Fails with the following error
✗ node test/examples/ephemeralPromiseMemoryLeak.js
<--- Last few GCs --->
[31511:0x6de4330] 39874 ms: Mark-Compact (reduce) 2048.2 (2083.6) -> 2047.3 (2083.9) MB, 1308.67 / 0.00 ms (average mu = 0.071, current mu = 0.001) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xcc062a node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0x104eb90 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0x104ee77 v8::internal::V8::FatalPr
Claim this issue to let others know you're working on it. You'll earn 20 points when you complete it!