I maintain a c++ module deasync (originally written by @vkurchatkin) which essentially exposes uv_run to jsLand in order to address some use cases that cannot be handled by other async-2-sync modules. A problem was reported recently that when deasync is involved in nested setTimeout calls with same timeout value, the process hung. It is illustrated by code
var deasync = require('deasync');
function async(cb) {
console.log('x');
setTimeout(function () {
console.log('y');
cb(null, 'value');
console.log('z');
}, 8);
}
setTimeout(function () {
console.log('A', deasync(async)());
}, 8); // changing 8 to, say 9, works
output
Changing one of the timeout values of setTimeout yields expected output
Problem is reproducible in latest Node version on at least Linux and Windows. I have run node in gdb session and found the problem is loop->active_handles has gone down to 0 after the inner setTimeout is called but before its handler is triggered, therefore the inner handler doesn't have a chance to run.
I think the cause is that timers of same timeout value are implemented using a linked list and only one handle is exposed to libuv. This handle is removed at the time the outer setTimeout handler is called.
By moving list.start(msecs, 0) in /lib/timers.js outside else block, I have verified the problem can be fixed. Will supply a PR later. What I am not clear is the impact of this change. Appreciate if someone can review the issue and my PR.
(P.S. I have read Node issue reporting guidelines and understand I am not supposed include dependencies. But deasync is simple, has no dependency by itself, and is easy to be re-factored into a dependency-less mixture of c++ and js code)
I maintain a c++ module deasync (originally written by @vkurchatkin) which essentially exposes
uv_runto jsLand in order to address some use cases that cannot be handled by other async-2-sync modules. A problem was reported recently that whendeasyncis involved in nestedsetTimeoutcalls with same timeout value, the process hung. It is illustrated by codeoutput
Changing one of the timeout values of
setTimeoutyields expected outputProblem is reproducible in latest Node version on at least Linux and Windows. I have run
nodein gdb session and found the problem isloop->active_handleshas gone down to 0 after the innersetTimeoutis called but before its handler is triggered, therefore the inner handler doesn't have a chance to run.I think the cause is that timers of same timeout value are implemented using a linked list and only one handle is exposed to libuv. This handle is removed at the time the outer
setTimeouthandler is called.By moving
list.start(msecs, 0)in/lib/timers.jsoutside else block, I have verified the problem can be fixed. Will supply a PR later. What I am not clear is the impact of this change. Appreciate if someone can review the issue and my PR.(P.S. I have read Node issue reporting guidelines and understand I am not supposed include dependencies. But
deasyncis simple, has no dependency by itself, and is easy to be re-factored into a dependency-less mixture of c++ and js code)