-
Notifications
You must be signed in to change notification settings - Fork 29.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
timer,domain: timers don't maintain order after exception #1271
Comments
FWIW:
|
It still points to larger problems within the timers impl though. |
Yes I definitely think that timers should guarantee order to the extent that browsers do, currently they don't do that even in normal code (normal as in not using domains) and code that assumes e.g. |
I'm pretty sure this has something to do with the fact that after an error timers.js re-schedules to start processing again on the next tick, but doesn't actually stop processing presently: https://github.com/nodejs/io.js/blob/master/lib/timers.js#L100 This diff fixes the test, but causes other problems, so I'm confused. diff --git a/lib/timers.js b/lib/timers.js
index 494c599..67b7a7a 100644
--- a/lib/timers.js
+++ b/lib/timers.js
@@ -99,6 +99,7 @@ function listOnTimeout() {
process.domain = null;
process.nextTick(listOnTimeoutNT, list);
process.domain = oldDomain;
+ return;
}
}
} if you're curious, here's the error log from |
Also, is it possible this only happens when the list gets processed at a time when all 3 should fire in the same tick? (i.e. >2ms) |
Just to add to this confusion, here's a slight change to the test script: 'use strict';
const domain = require('domain').create();
const print = process._rawDebug;
domain.run(function() {
setTimeout(function() { throw Error('FAIL') }, 1);
setTimeout(function() { print('timeout 1') }, 1);
setImmediate(function() { print('immediate 1') });
setTimeout(function() { print('timeout 2') }, 2);
setImmediate(function() { print('immediate 2') });
});
domain.once('error', function() {}); I've gotten the output of:
and
|
@trevnorris @bnoordhuis ... running this against master currently, given about 100 runs each on @bnoordhuis' original and @trevnorris' revised version and I'm not seeing any variability in the ordering over timer events. Could this one have been fixed? |
Strange. I'll investigate soon. |
btw, ran the tests on OSX in case it happens to matter. Have not tried the same tests against v5 or v4 yet. |
Looks like I can still reproduce, at about the same rate. Make sure you use a command looper. Here's a modified test to accommodate that. const domain = require('domain').create();
var first = false;
domain.run(function() {
setTimeout(function() { throw Error('FAIL'); }, 1);
setTimeout(function() {
first = true;
console.log('timeout 1');
}, 1);
setTimeout(function() {
console.log('timeout 2');
if (first === false) {
console.log('timers reordered!')
process.exit(1);
}
}, 2);
});
domain.once('error', function() {}); ... shell scripts: (fish-shell & bash) while ../node/node timers-reorder.js
end while ../node/node timers-reorder.js; do :; done |
Revisited this old issue with current master and v6.6.0:
|
Just repo'd on OS X 10.10.5. @imyller did you try my test case on repeat? Maybe we should just call this "one of those odd domain bugs", close the issue, and call it a day. Or I could spend like a week debugging it but that is probably not a good use of my time. |
@Fishrock123 Yes, I just let it loop with shell while-do on OS X 10.11.6 and couldn't reproduce. With Linux test environment this is very easy to reproduce with only few repeats. Your call, but I personally wouldn't close the issue yet because the reproduceable problem still exists and the cause is not yet understood. |
I suppose. I suspect unless someone else throws a considerable amount of time at it, this will just go away when domains are likely removed in a couple years. I'm able to help with the timers side of things if anyone wants to take a look into it. Maybe @misterdjules would actually be the best to take a look? |
I took a crack at this and hopefully what I found is useful :-) The solution seems to be skip all further list[x] to the next tick. |
@jBarz that sounds reasonable, could you submit a PR? |
Hmmmm that does actually make sense now that I think about it. |
I added @Fishrock123 's test case from #1271 (comment) |
Fixed by 9dac165 |
PR-URL: nodejs#10522 Fixes: nodejs#1271 Reviewed-By: Sam Roberts <vieuxtech@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Gibson Fahnestock <gibfahn@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
Expected output:
Actual output:
(EDIT: I forgot to mention that you may need to run the test a few times.)
The text was updated successfully, but these errors were encountered: