Permalink
Browse files

timers: add v0.4 compatibility hack

If a timer callback throws and the user's uncaughtException handler ignores the
exception, other timers that expire on the current tick should still run.

If #2582 goes through, this hack should be removed.

Fixes #2631.
  • Loading branch information...
1 parent ca4b91a commit b221fe9b29f7dd834af9716e077bc05a05156d64 @bnoordhuis bnoordhuis committed Jan 29, 2012
Showing with 67 additions and 1 deletion.
  1. +15 −1 lib/timers.js
  2. +52 −0 test/simple/test-timers-uncaught-exception.js
View
@@ -81,7 +81,21 @@ function insert(item, msecs) {
} else {
L.remove(first);
assert(first !== L.peek(list));
- if (first._onTimeout) first._onTimeout();
+
+ if (!first._onTimeout) continue;
+
+ // v0.4 compatibility: if the timer callback throws and the user's
+ // uncaughtException handler ignores the exception, other timers that
+ // expire on this tick should still run. If #2582 goes through, this
+ // hack should be removed.
+ //
+ // https://github.com/joyent/node/issues/2631
+ try {
+ first._onTimeout();
+ } catch (e) {
+ if (!process.listeners('uncaughtException').length) throw e;
+ process.emit('uncaughtException', e);
+ }
}
}
@@ -0,0 +1,52 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+
+var exceptions = 0;
+var timer1 = 0;
+var timer2 = 0;
+
+// the first timer throws...
+setTimeout(function() {
+ timer1++;
+ throw new Error('BAM!');
+}, 100);
+
+// ...but the second one should still run
+setTimeout(function() {
+ assert.equal(timer1, 1);
+ timer2++;
+}, 100);
+
+function uncaughtException(err) {
+ assert.equal(err.message, 'BAM!');
+ exceptions++;
+}
+process.on('uncaughtException', uncaughtException);
+
+process.on('exit', function() {
+ process.removeListener('uncaughtException', uncaughtException);
+ assert.equal(exceptions, 1);
+ assert.equal(timer1, 1);
+ assert.equal(timer2, 1);
+});

0 comments on commit b221fe9

Please sign in to comment.