diff options
-rw-r--r-- | lib/domain.js | 7 | ||||
-rw-r--r-- | lib/events.js | 16 | ||||
-rw-r--r-- | test/simple/test-domain-exit-dispose.js | 67 |
3 files changed, 85 insertions, 5 deletions
diff --git a/lib/domain.js b/lib/domain.js index e219c5e507..31f5df4932 100644 --- a/lib/domain.js +++ b/lib/domain.js @@ -59,7 +59,7 @@ function uncaughtHandler(er) { domain_thrown: true }); exports.active.emit('error', er); - exports.active.exit(); + if (exports.active) exports.active.exit(); } else if (process.listeners('uncaughtException').length === 1) { // if there are other handlers, then they'll take care of it. // but if not, then we need to crash now. @@ -207,8 +207,13 @@ Domain.prototype.bind = function(cb, interceptError) { }; Domain.prototype.dispose = function() { + console.error('dispose', this, exports.active, process.domain) + if (this._disposed) return; + // if we're the active domain, then get out now. + this.exit(); + this.emit('dispose'); // remove error handlers. diff --git a/lib/events.js b/lib/events.js index c2b604f892..e0af38066a 100644 --- a/lib/events.js +++ b/lib/events.js @@ -45,6 +45,8 @@ EventEmitter.prototype.setMaxListeners = function(n) { this._maxListeners = n; }; +// non-global reference, for speed. +var PROCESS; EventEmitter.prototype.emit = function() { var type = arguments[0]; @@ -77,7 +79,10 @@ EventEmitter.prototype.emit = function() { if (typeof handler == 'function') { if (this.domain) { - this.domain.enter(); + PROCESS = PROCESS || process; + if (this !== PROCESS) { + this.domain.enter(); + } } switch (arguments.length) { // fast cases @@ -97,14 +102,17 @@ EventEmitter.prototype.emit = function() { for (var i = 1; i < l; i++) args[i - 1] = arguments[i]; handler.apply(this, args); } - if (this.domain) { + if (this.domain && this !== PROCESS) { this.domain.exit(); } return true; } else if (isArray(handler)) { if (this.domain) { - this.domain.enter(); + PROCESS = PROCESS || process; + if (this !== PROCESS) { + this.domain.enter(); + } } var l = arguments.length; var args = new Array(l - 1); @@ -114,7 +122,7 @@ EventEmitter.prototype.emit = function() { for (var i = 0, l = listeners.length; i < l; i++) { listeners[i].apply(this, args); } - if (this.domain) { + if (this.domain && this !== PROCESS) { this.domain.exit(); } return true; diff --git a/test/simple/test-domain-exit-dispose.js b/test/simple/test-domain-exit-dispose.js new file mode 100644 index 0000000000..fd990911c1 --- /dev/null +++ b/test/simple/test-domain-exit-dispose.js @@ -0,0 +1,67 @@ +// 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.js'); +var assert = require('assert'); +var domain = require('domain'); +var disposalFailed = false; + +// no matter what happens, we should increment a 10 times. +var a = 0; +log(); +function log(){ + console.log(a++, process.domain); + if (a < 10) setTimeout(log, 20); +} + +// in 50ms we'll throw an error. +setTimeout(err, 50); +function err(){ + var d = domain.create(); + d.on('error', handle); + d.run(err2); + + function err2() { + // this timeout should never be called, since the domain gets + // disposed when the error happens. + setTimeout(function() { + console.error('This should not happen.'); + disposalFailed = true; + process.exit(1); + }); + + // this function doesn't exist, and throws an error as a result. + err3(); + } + + function handle(e) { + // this should clean up everything properly. + d.dispose(); + console.error(e); + console.error('in handler', process.domain, process.domain === d); + } +} + +process.on('exit', function() { + assert.equal(a, 10); + assert.equal(disposalFailed, false); + console.log('ok'); +}); |