diff options
author | Benjamin Thomas <benjamin@benjaminthomas.org> | 2010-08-27 02:50:12 -0600 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2010-08-27 22:13:50 -0700 |
commit | 57642e23497d5698aa4c5b8a44edff7b265c2283 (patch) | |
tree | 49604fabc620ac4e5f55ed52b3bc1c5905daabc0 | |
parent | 4fdebab005a4c52310f310110a33a5884ee1b86c (diff) | |
download | node-new-57642e23497d5698aa4c5b8a44edff7b265c2283.tar.gz |
Fix process.nextTick so thrown errors don't confuse it.
If the function for a process.nextTick throws an error, then the
splice() never removes that function from the nextTickQueue array. This
makes sure the functions that have been run in _tickCallback get removed
regardless of errors.
Also add a test for this.
-rw-r--r-- | src/node.js | 12 | ||||
-rw-r--r-- | test/simple/test-next-tick-errors.js | 41 |
2 files changed, 51 insertions, 2 deletions
diff --git a/src/node.js b/src/node.js index 82a5937e2e..f329c0055c 100644 --- a/src/node.js +++ b/src/node.js @@ -49,9 +49,17 @@ var nextTickQueue = []; process._tickCallback = function () { var l = nextTickQueue.length; if (l === 0) return; - for (var i = 0; i < l; i++) { - nextTickQueue[i](); + + try { + for (var i = 0; i < l; i++) { + nextTickQueue[i](); + } } + catch(e) { + nextTickQueue.splice(0, i+1); + throw e; + } + nextTickQueue.splice(0, l); }; diff --git a/test/simple/test-next-tick-errors.js b/test/simple/test-next-tick-errors.js new file mode 100644 index 0000000000..421baa999a --- /dev/null +++ b/test/simple/test-next-tick-errors.js @@ -0,0 +1,41 @@ +common = require("../common"); +assert = common.assert + +var order = [], + exceptionHandled = false; + +// This nextTick function will throw an error. It should only be called once. +// When it throws an error, it should still get removed from the queue. +process.nextTick(function() { + order.push('A'); + // cause an error + what(); +}); + +// This nextTick function should remain in the queue when the first one +// is removed. +process.nextTick(function() { + order.push('C'); +}); + +process.addListener('uncaughtException', function() { + if (!exceptionHandled) { + exceptionHandled = true; + order.push('B'); + // We call process.nextTick here to make sure the nextTick queue is + // processed again. If everything goes according to plan then when the queue + // gets ran there will be two functions with this being the second. + process.nextTick(function() { + order.push('D'); + }); + } + else { + // If we get here then the first process.nextTick got called twice + order.push('OOPS!'); + } +}); + +process.addListener('exit', function() { + assert.deepEqual(['A','B','C','D'], order); +}); + |