setTimeout can’t work well after the process is blocked #15447
Description
node.js version: 4d9c81b (latest version), v0.10.33, node-v0.12.2
Platform: Ubuntu 14.04.1 LTS
Architecture: x86_64
var block = require('bindings')('hello'); // c++ addon
var a = function() {
var timer = (new Date()).getTime();
console.log('before block:'+timer);
block.hello(); // will be block at some time
timer = (new Date()).getTime();
console.log('after block:'+timer);
setTimeout(a, 5000);
};
a();
In the above script, function a will be executed very 5000 milliseconds if the block.hello is not blocked; But if the block.hello is blocked in c++ code, the time point which function a will be executed again is much larger than 5000 milliseconds after block.hello is unblocked. The following is the output of the above script:
1 before block:1429079335210
2 after block:1429079335210
3 before block:1429079340215
4 after block:1429079366741
5 before block:1429079398298
6 after block:1429079398299
7 before block:1429079403304
8 after block:1429079403304
Time interval between line2 and line 3 is 5005;
Time interval between line4 and line 5 is 31557;
Time interval between line6 and line 7 is 5005;
block.hello is blocked and unblocked between line 3 and line 4.
How to reproduce the issue?
- Download the tar file and decompress; https://www.dropbox.com/s/1y299n1y1uy69ij/node_js_debug.tar?dl=0
- cd node_js_debug;
- sh build.sh;
- node a.js;
- In another terminal, ./setFrontEndApp 123456; after a while, ./setFrontEndApp 0
How to fix?
I find we should recalculate now each time when processing the pending time events.
diff --git a/lib/timers.js b/lib/timers.js
index 68f87d7..c6af7f9 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -80,11 +80,10 @@ function listOnTimeout() {
debug('timeout callback %d', msecs);
- var now = Timer.now();
- debug('now: %s', now);
-
var diff, first, threw;
while (first = L.peek(list)) {
+ var now = Timer.now();
+ debug('now: %s', now);
diff = now - first._idleStart;
if (diff < msecs) {
list.start(msecs - diff, 0);