Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
domain: move error handling directly into instance
Browse files Browse the repository at this point in the history
Instead of doing all the domain handling in core, allow the domain to
set an error handler that'll take care of it all. This way the domain
error handling can be abstracted enough for any user to use it.
  • Loading branch information
trevnorris committed Aug 23, 2013
1 parent 7555227 commit 467e00e
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 52 deletions.
56 changes: 54 additions & 2 deletions lib/domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ process._setupDomainUse(_domain, _domain_flag);

exports.Domain = Domain;

exports.create = exports.createDomain = function(cb) {
return new Domain(cb);
exports.create = exports.createDomain = function() {
return new Domain();
};

// it's possible to enter one domain while already inside
Expand All @@ -74,6 +74,58 @@ function Domain() {
this.members = [];
}

Domain.prototype.members = undefined;
Domain.prototype._disposed = undefined;

// Called by process._fatalException in case an error was thrown.
Domain.prototype._errorHandler = function errorHandler(er) {
var caught = false;
// ignore errors on disposed domains.
//
// XXX This is a bit stupid. We should probably get rid of
// domain.dispose() altogether. It's almost always a terrible
// idea. --isaacs
if (this._disposed)
return true;

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();
}
if (stack.length) {
exports.active = process.domain = stack[stack.length - 1];
caught = process._fatalException(er2);
} else {
caught = false;
}
return caught;
}
return caught;
};

Domain.prototype.enter = function() {
if (this._disposed) return;

Expand Down
57 changes: 7 additions & 50 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,60 +216,15 @@
};

startup.processFatal = function() {
// call into the active domain, or emit uncaughtException,
// and exit if there are no listeners.
process._fatalException = function(er) {
var caught = false;
if (process.domain) {
var domain = process.domain;
var domainModule = NativeModule.require('domain');
var domainStack = domainModule._stack;

// ignore errors on disposed domains.
//
// XXX This is a bit stupid. We should probably get rid of
// domain.dispose() altogether. It's almost always a terrible
// idea. --isaacs
if (domain._disposed)
return true;

er.domain = domain;
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 = domain.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.
var domainModule = NativeModule.require('domain');
domainStack.length = 0;
domainModule.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 (domain === domainModule.active)
domainStack.pop();
if (domainStack.length) {
var parentDomain = domainStack[domainStack.length - 1];
process.domain = domainModule.active = parentDomain;
caught = process._fatalException(er2);
} else
caught = false;
}
if (process.domain && process.domain._errorHandler) {
caught = process.domain._errorHandler(er);
} else {
caught = process.emit('uncaughtException', er);
}

// if someone handled it, then great. otherwise, die in C++ land
// since that means that we'll exit the process, emit the 'exit' event
if (!caught) {
Expand All @@ -281,10 +236,12 @@
} catch (er) {
// nothing to be done about it at this point.
}
}

// if we handled an error, then make sure any ticks get processed
if (caught)
} else {
setImmediate(process._tickCallback);
}

return caught;
};
};
Expand Down

0 comments on commit 467e00e

Please sign in to comment.