Skip to content

Commit 515dd24

Browse files
theanarkhtargos
authored andcommitted
lib: fix timer leak
PR-URL: #53337Fixes: #53335 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Chemi Atlow <chemi@atlow.co.il> Reviewed-By: Feng Yu <F3n67u@outlook.com> Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
1 parent cf375e7 commit 515dd24

4 files changed

Lines changed: 37 additions & 6 deletions

File tree

‎lib/internal/timers.js‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ const timerListQueue = new PriorityQueue(compareTimersLists, setPosition);
152152
// - value = linked list
153153
consttimerListMap={__proto__: null};
154154

155+
// This stores all the known timer async ids to allow users to clearTimeout and
156+
// clearInterval using those ids, to match the spec and the rest of the web
157+
// platform.
158+
constknownTimersById={__proto__: null};
159+
155160
functioninitAsyncResource(resource,type){
156161
constasyncId=resource[async_id_symbol]=newAsyncId();
157162
consttriggerAsyncId=
@@ -550,6 +555,9 @@ function getTimerCallbacks(runNextTicks) {
550555
if(!timer._destroyed){
551556
timer._destroyed=true;
552557

558+
if(timer[kHasPrimitive])
559+
deleteknownTimersById[asyncId];
560+
553561
if(timer[kRefed])
554562
timeoutInfo[0]--;
555563

@@ -580,6 +588,9 @@ function getTimerCallbacks(runNextTicks) {
580588
}elseif(!timer._idleNext&&!timer._idlePrev&&!timer._destroyed){
581589
timer._destroyed=true;
582590

591+
if(timer[kHasPrimitive])
592+
deleteknownTimersById[asyncId];
593+
583594
if(timer[kRefed])
584595
timeoutInfo[0]--;
585596

@@ -683,4 +694,5 @@ module.exports = {
683694
timerListQueue,
684695
decRefCount,
685696
incRefCount,
697+
knownTimersById,
686698
};

‎lib/timers.js‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const {
5252
active,
5353
unrefActive,
5454
insert,
55+
knownTimersById,
5556
}=require('internal/timers');
5657
const{
5758
promisify: {custom: customPromisify},
@@ -71,11 +72,6 @@ const {
7172
emitDestroy,
7273
}=require('internal/async_hooks');
7374

74-
// This stores all the known timer async ids to allow users to clearTimeout and
75-
// clearInterval using those ids, to match the spec and the rest of the web
76-
// platform.
77-
constknownTimersById={__proto__: null};
78-
7975
// Remove a timer. Cancels the timeout and resets the relevant timer properties.
8076
functionunenroll(item){
8177
if(item._destroyed)

‎test/fixtures/source-map/output/source_map_throw_set_immediate.snapshot‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
Error: goodbye
77
at Hello (*uglify-throw-original.js:5:9)
88
at Immediate.<anonymous> (*uglify-throw-original.js:9:3)
9-
at process.processImmediate (node:internal*timers:478:21)
9+
at process.processImmediate (node:internal*timers:483:21)
1010

1111
Node.js *
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
// Flags: --expose-gc
3+
require('../common');
4+
constonGC=require('../common/ongc');
5+
6+
// See https://github.com/nodejs/node/issues/53335
7+
constpoller=setInterval(()=>{
8+
global.gc();
9+
},100);
10+
11+
letcount=0;
12+
13+
for(leti=0;i<10;i++){
14+
consttimer=setTimeout(()=>{},0);
15+
onGC(timer,{
16+
ongc: ()=>{
17+
if(++count===10){
18+
clearInterval(poller);
19+
}
20+
}
21+
});
22+
console.log(+timer);
23+
}

0 commit comments

Comments
 (0)