summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorisaacs <i@izs.me>2012-09-20 15:13:36 -0700
committerisaacs <i@izs.me>2012-09-21 09:22:50 -0700
commit040057167653e8e6ce4d5a368fbc6d73bb541e28 (patch)
tree09752bc5b51dce7c13f5e7f9b60f213ba9e91a98 /lib
parent43a2b291822416eb5f72d17ad250e7542abb0581 (diff)
downloadandroid-node-v8-040057167653e8e6ce4d5a368fbc6d73bb541e28.tar.gz
android-node-v8-040057167653e8e6ce4d5a368fbc6d73bb541e28.tar.bz2
android-node-v8-040057167653e8e6ce4d5a368fbc6d73bb541e28.zip
domain: Properly exit() on domain disposal
This addresses #4034. There are two problems happening: 1. The domain is not exited automatically when calling dispose() on it. Then, since the domain is disposed, attempting to exit it again will do nothing. 2. The active domain is stored on process.domain. Since thrown errors call `process.emit('uncaughtException', er)`, and the process is an event emitter with a `.domain` member, it re-enters the domain a second time before calling the error handler, pushing it onto the stack again. Thus, if the handler calls `domain.dispose()`, then the domain is now on the stack twice, and cannot be exited properly. Since the domain is disposed, any subsequent IO will be no-op'ed, since we've declared that this context is done and best forgotten. The solution here is twofold: 1. In EventEmitter.emit, do not enter the domain if `this===process`. 2. Automatically exit the domain when calling `domain.dispose()`.
Diffstat (limited to 'lib')
-rw-r--r--lib/domain.js7
-rw-r--r--lib/events.js16
2 files changed, 18 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;