Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bentomas/553061 to your computer and use it in GitHub Desktop.
Save bentomas/553061 to your computer and use it in GitHub Desktop.
From 401d78805122b8edbb56b1d3d54e7e81148cb94a Mon Sep 17 00:00:00 2001
From: Benjamin Thomas <benjamin@benjaminthomas.org>
Date: Fri, 27 Aug 2010 02:50:12 -0600
Subject: [PATCH] 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.
---
src/node.js | 12 ++++++++-
test/simple/test-next-tick-errors.js | 41 ++++++++++++++++++++++++++++++++++
2 files changed, 51 insertions(+), 2 deletions(-)
create mode 100644 test/simple/test-next-tick-errors.js
diff --git a/src/node.js b/src/node.js
index 82a5937..f329c00 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 0000000..421baa9
--- /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);
+});
+
--
1.6.5.7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment