Skip to content

Commit

Permalink
timers: fix processing of nested same delay timers
Browse files Browse the repository at this point in the history
Whenever a timer with a specific timeout value creates a new timer with
the same timeout, the newly added timer might be processed immediately
in the same tick of the event loop instead of during the next tick of
the event loop at the earliest.

Fixes nodejs#25607
  • Loading branch information
whitlockjc committed Jul 24, 2015
1 parent e192f61 commit 9bb2b67
Showing 1 changed file with 28 additions and 6 deletions.
34 changes: 28 additions & 6 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,35 @@ function listOnTimeout() {

var first;
while (first = L.peek(list)) {
// If the previous iteration caused a timer to be added,
// update the value of "now" so that timing computations are
// done correctly. See test/simple/test-timers-blocking-callback.js
// for more information.
// This handles the case of a timer that was created within a timers
// callback with the same timeout value. For instance, when processing the
// timer that would call `bar` in such code:
//
// setTimeout(function foo() { setTimeout(function bar() {}, 0) }, 0);
//
// or
//
// setTimeout(function foo() { setTimeout(function bar() {}, 500) }, 500);
//
// We want to make sure that newly added timer fires in the next turn of the
// event loop at the earliest. So even if it's already expired now,
// reschedule it to fire later.
//
// At that point, it's not necessary to process any other timer in that
// list, because any remaining timer has been added within a callback of a
// timer that has already been processed, and thus needs to be processed at
// the earliest not in the current tick, but when the rescheduled timer will
// expire.
//
// See: https://github.com/joyent/node/issues/25607
if (now < first._monotonicStartTime) {
now = Timer.now();
debug('now: %d', now);
var timeRemaining = msecs - (Timer.now() - first._monotonicStartTime);
if (timeRemaining < 0) {
timeRemaining = 0;
}
debug(msecs + ' list wait because timer was added from another timer');
list.start(timeRemaining, 0);
return;
}

var diff = now - first._monotonicStartTime;
Expand Down

0 comments on commit 9bb2b67

Please sign in to comment.