summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Thomas <benjamin@benjaminthomas.org>2010-08-27 02:50:12 -0600
committerRyan Dahl <ry@tinyclouds.org>2010-08-27 22:13:50 -0700
commit57642e23497d5698aa4c5b8a44edff7b265c2283 (patch)
tree49604fabc620ac4e5f55ed52b3bc1c5905daabc0
parent4fdebab005a4c52310f310110a33a5884ee1b86c (diff)
downloadnode-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.js12
-rw-r--r--test/simple/test-next-tick-errors.js41
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);
+});
+