Skip to content

Commit

Permalink
timers: fix refreshed timers exiting too early
Browse files Browse the repository at this point in the history
If a timer is refreshed in its callback, we should not decrease `refCount`
to prevent exiting event loop ahead of time.

Fixes: nodejs#26642
  • Loading branch information
starkwang committed Mar 15, 2019
1 parent 107c95d commit 104b605
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 2 deletions.
3 changes: 2 additions & 1 deletion lib/internal/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -98,7 +99,7 @@ Timeout.prototype.refresh = function() {
getTimers().active(this);
else
getTimers()._unrefActive(this);

this._refreshed = true;
return this;
};

Expand Down
3 changes: 2 additions & 1 deletion lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 12 additions & 0 deletions test/parallel/test-timers-refresh.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

0 comments on commit 104b605

Please sign in to comment.