From 104b605b93e5163c0a53be7f4172f40ea5e255f3 Mon Sep 17 00:00:00 2001 From: Weijia Wang Date: Fri, 15 Mar 2019 10:30:44 +0800 Subject: [PATCH] timers: fix refreshed timers exiting too early If a timer is refreshed in its callback, we should not decrease `refCount` to prevent exiting event loop ahead of time. Fixes: https://github.com/nodejs/node/issues/26642 --- lib/internal/timers.js | 3 ++- lib/timers.js | 3 ++- test/parallel/test-timers-refresh.js | 12 ++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/lib/internal/timers.js b/lib/internal/timers.js index e265c85dcc1a3d..ccc75cb57b1173 100644 --- a/lib/internal/timers.js +++ b/lib/internal/timers.js @@ -76,6 +76,7 @@ function Timeout(callback, after, args, isRepeat) { this._timerArgs = args; this._repeat = isRepeat ? after : null; this._destroyed = false; + this._refreshed = false; this[kRefed] = null; @@ -98,7 +99,7 @@ Timeout.prototype.refresh = function() { getTimers().active(this); else getTimers()._unrefActive(this); - + this._refreshed = true; return this; }; diff --git a/lib/timers.js b/lib/timers.js index a81e8bc71ef70a..8faa86b79b8fe6 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -342,8 +342,9 @@ function listOnTimeout(list, now) { start = getLibuvNow(); insert(timer, timer[kRefed], start); } else { - if (timer[kRefed]) + if (timer[kRefed] && !timer._refreshed) refCount--; + timer._refreshed = false; timer[kRefed] = null; if (destroyHooksExist() && !timer._destroyed) { diff --git a/test/parallel/test-timers-refresh.js b/test/parallel/test-timers-refresh.js index 597d5c9241947a..99502e78f5abe9 100644 --- a/test/parallel/test-timers-refresh.js +++ b/test/parallel/test-timers-refresh.js @@ -87,3 +87,15 @@ const { setUnrefTimeout } = require('internal/timers'); strictEqual(timer.refresh(), timer); } + +// refresh timeout in callback +{ + let called = 0; + const timer = setTimeout(common.mustCall(() => { + called += 1; + if (called === 2) { + clearTimeout(timer); + } + timer.refresh(); + }, 2), 1); +}