From 47a984ada005d4db150b3d0ebd71b560411e7470 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Wed, 31 Jan 2018 13:37:01 -0500 Subject: [PATCH] timers: prevent event loop blocking When an interval takes as long or longer to run as its timeout setting and the roundtrip from rearm() to its deferal takes exactly 1ms, that interval can then block the event loop. This is an edge case of another recently fixed bug (which in itself was an edge case). PR-URL: https://github.com/nodejs/node/pull/18486 Refs: https://github.com/nodejs/node/pull/15072 Reviewed-By: James M Snell Reviewed-By: Ruben Bridgewater Reviewed-By: Jeremiah Senkpiel --- lib/timers.js | 2 +- .../test-timers-set-interval-excludes-callback-duration.js | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/timers.js b/lib/timers.js index 734c58712d6f6c..79fc432dcdf3d7 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -238,7 +238,7 @@ TimerWrap.prototype[kOnTimeout] = function listOnTimeout(now) { // This happens if there are more timers scheduled for later in the list. if (diff < msecs) { var timeRemaining = msecs - (TimerWrap.now() - timer._idleStart); - if (timeRemaining < 0) { + if (timeRemaining <= 0) { timeRemaining = 1; } this.start(timeRemaining); diff --git a/test/sequential/test-timers-set-interval-excludes-callback-duration.js b/test/sequential/test-timers-set-interval-excludes-callback-duration.js index d47659d7b395ab..cb60d7e45270d6 100644 --- a/test/sequential/test-timers-set-interval-excludes-callback-duration.js +++ b/test/sequential/test-timers-set-interval-excludes-callback-duration.js @@ -9,9 +9,16 @@ const t = setInterval(() => { cntr++; if (cntr === 1) { common.busyLoop(100); + // ensure that the event loop passes before the second interval + setImmediate(() => assert.strictEqual(cntr, 1)); first = Timer.now(); } else if (cntr === 2) { assert(Timer.now() - first < 100); clearInterval(t); } }, 100); +const t2 = setInterval(() => { + if (cntr === 2) { + clearInterval(t2); + } +}, 100);