summaryrefslogtreecommitdiff
path: root/lib/domain.js
diff options
context:
space:
mode:
authorJeremy Whitlock <jwhitlock@apache.org>2015-10-05 13:08:53 -0700
committerJulien Gilli <julien.gilli@joyent.com>2015-10-05 18:12:43 -0700
commit77a10ed05f1e413818d29f07cbb268108b1f08fa (patch)
tree525e3e0d9c31b94baf34f9e689e95f657df00bf9 /lib/domain.js
parent49dec1afd8c310d6995a62893d59b171e2f021cc (diff)
downloadnode-new-77a10ed05f1e413818d29f07cbb268108b1f08fa.tar.gz
src: fix --abort-on-uncaught-exception
Revert 0af4c9ea7434e4f505dbe071357e4bc3b4ab2a8a, parts of 921f2de6cf999b5a4663615e37967b4269d755fe and port https://github.com/nodejs/node-v0.x-archive/pull/25835 from v0.12 to master so that node aborts at the right time when an error is thrown and --abort-on-uncaught-exception is used. Fixes #3035. PR: #3036 PR-URL: https://github.com/nodejs/node/pull/3036 Reviewed-By: Ben Noordhuis <ben@strongloop.com>
Diffstat (limited to 'lib/domain.js')
-rw-r--r--lib/domain.js88
1 files changed, 59 insertions, 29 deletions
diff --git a/lib/domain.js b/lib/domain.js
index 4ee4d71b19..b6321a20f8 100644
--- a/lib/domain.js
+++ b/lib/domain.js
@@ -59,6 +59,20 @@ Domain.prototype._disposed = undefined;
// Called by process._fatalException in case an error was thrown.
Domain.prototype._errorHandler = function errorHandler(er) {
var caught = false;
+ var self = this;
+
+ function emitError() {
+ var handled = self.emit('error', er);
+
+ // Exit all domains on the stack. Uncaught exceptions end the
+ // current tick and no domains should be left on the stack
+ // between ticks.
+ stack.length = 0;
+ exports.active = process.domain = null;
+
+ return handled;
+ }
+
// ignore errors on disposed domains.
//
// XXX This is a bit stupid. We should probably get rid of
@@ -71,38 +85,54 @@ Domain.prototype._errorHandler = function errorHandler(er) {
er.domain = this;
er.domainThrown = true;
}
- // wrap this in a try/catch so we don't get infinite throwing
- try {
- // One of three things will happen here.
- //
- // 1. There is a handler, caught = true
- // 2. There is no handler, caught = false
- // 3. It throws, caught = false
- //
- // If caught is false after this, then there's no need to exit()
- // the domain, because we're going to crash the process anyway.
- caught = this.emit('error', er);
- // Exit all domains on the stack. Uncaught exceptions end the
- // current tick and no domains should be left on the stack
- // between ticks.
- stack.length = 0;
- exports.active = process.domain = null;
- } catch (er2) {
- // The domain error handler threw! oh no!
- // See if another domain can catch THIS error,
- // or else crash on the original one.
- // If the user already exited it, then don't double-exit.
- if (this === exports.active) {
- stack.pop();
+ // The top-level domain-handler is handled separately.
+ //
+ // The reason is that if V8 was passed a command line option
+ // asking it to abort on an uncaught exception (currently
+ // "--abort-on-uncaught-exception"), we want an uncaught exception
+ // in the top-level domain error handler to make the
+ // process abort. Using try/catch here would always make V8 think
+ // that these exceptions are caught, and thus would prevent it from
+ // aborting in these cases.
+ if (stack.length === 1) {
+ try {
+ // Set the _emittingTopLevelDomainError so that we know that, even
+ // if technically the top-level domain is still active, it would
+ // be ok to abort on an uncaught exception at this point
+ process._emittingTopLevelDomainError = true;
+ caught = emitError();
+ } finally {
+ process._emittingTopLevelDomainError = false;
}
- if (stack.length) {
- exports.active = process.domain = stack[stack.length - 1];
- caught = process._fatalException(er2);
- } else {
- caught = false;
+ } else {
+ // wrap this in a try/catch so we don't get infinite throwing
+ try {
+ // One of three things will happen here.
+ //
+ // 1. There is a handler, caught = true
+ // 2. There is no handler, caught = false
+ // 3. It throws, caught = false
+ //
+ // If caught is false after this, then there's no need to exit()
+ // the domain, because we're going to crash the process anyway.
+ caught = emitError();
+ } catch (er2) {
+ // The domain error handler threw! oh no!
+ // See if another domain can catch THIS error,
+ // or else crash on the original one.
+ // If the user already exited it, then don't double-exit.
+ if (this === exports.active) {
+ stack.pop();
+ }
+ if (stack.length) {
+ exports.active = process.domain = stack[stack.length - 1];
+ caught = process._fatalException(er2);
+ } else {
+ caught = false;
+ }
+ return caught;
}
- return caught;
}
return caught;
};