handle destroy methods better: stop all polling on the event loop.

This commit is contained in:
Christopher Jeffrey 2015-07-29 19:20:53 -07:00
parent 1628e7d629
commit debbc864e4
5 changed files with 57 additions and 15 deletions

View File

@ -443,12 +443,35 @@ Program.prototype._listenOutput = function() {
Program.prototype.destroy = function() {
var index = Program.instances.indexOf(this);
if (~index) {
Program.instances.splice(index, 1);
Program.total--;
this.flush();
this._exiting = true;
if (Program.total === 0) {
Program.global = null;
process.removeAllListeners('exit');
this.input.removeAllListeners('keypress');
this.input.removeAllListeners('data');
this.input.removeAllListeners('newListener');
this.output.removeAllListeners('resize');
if (this.input.setRawMode) {
if (this.input.isRaw) {
this.input.setRawMode(false);
}
if (!this.input.destroyed) {
this.input.pause();
}
}
}
this.destroyed = true;
this.emit('destroy');
}
};

View File

@ -305,12 +305,6 @@ Element.prototype.free = function() {
delete this._slisteners;
};
Element.prototype.destroy = function() {
this.detach();
this.free();
this.emit('destroy');
};
Element.prototype.hide = function() {
if (this.hidden) return;
this.clearPos();

View File

@ -135,6 +135,19 @@ Node.prototype.detach = function() {
if (this.parent) this.parent.remove(this);
};
Node.prototype.free = function() {
return;
};
Node.prototype.destroy = function() {
this.detach();
this.forDescendants(function(el) {
el.free();
el.destroyed = true;
el.emit('destroy');
}, this);
};
Node.prototype.forDescendants = function(iter, s) {
if (s) iter(this);
this.children.forEach(function emit(el) {

View File

@ -35,7 +35,7 @@ function Screen(options) {
return new Screen(options);
}
Screen.bind(this);
Screen.bind(this, options || {});
options = options || {};
if (options.rsety && options.listen) {
@ -195,9 +195,12 @@ Screen.instances = [];
Screen.signals = true;
Screen.bind = function(screen) {
Screen.bind = function(screen, options) {
if (!Screen.global) {
Screen.global = screen;
if (options.signals === false) {
Screen.signals = false;
}
}
if (!~Screen.instances.indexOf(screen)) {
@ -209,7 +212,7 @@ Screen.bind = function(screen) {
Screen._bound = true;
process.on('uncaughtException', function(err) {
if (process.listeners('uncaughtException').length > Screen.total) {
if (process.listeners('uncaughtException').length > 1) {
return;
}
Screen.instances.slice().forEach(function(screen) {
@ -217,6 +220,9 @@ Screen.bind = function(screen) {
});
err = err || new Error('Uncaught Exception.');
console.error(err.stack ? err.stack + '' : err + '');
if (Screen.total === 0) {
return process.exit(1);
}
nextTick(function() {
process.exit(1);
});
@ -227,9 +233,12 @@ Screen.bind = function(screen) {
if (Screen.signals) {
['SIGTERM', 'SIGINT', 'SIGQUIT'].forEach(function(signal) {
process.on(signal, function() {
if (process.listeners(signal).length > Screen.total) {
if (process.listeners(signal).length > 1) {
return;
}
if (Screen.total === 0) {
return process.exit(0);
}
nextTick(function() {
process.exit(0);
});
@ -383,6 +392,7 @@ Screen.prototype.postEnter = function() {
}
};
Screen.prototype._destroy = Screen.prototype.destroy;
Screen.prototype.destroy = function() {
this.leave();
@ -390,10 +400,16 @@ Screen.prototype.destroy = function() {
if (~index) {
Screen.instances.splice(index, 1);
Screen.total--;
if (Screen.total === 0) {
Screen.global = null;
process.removeAllListeners('uncaughtException');
}
this.destroyed = true;
this.emit('destroy');
this._destroy();
}
this.program.destroy();

View File

@ -209,6 +209,7 @@ Terminal.prototype.bootstrap = function() {
this.on('destroy', function() {
self.kill();
self.screen.program.removeListener('data', self._onData);
});
if (this.handler) {
@ -252,11 +253,6 @@ Terminal.prototype.bootstrap = function() {
});
this.screen._listenKeys(this);
this.on('destroy', function() {
self.screen.program.removeListener('data', self._onData);
self.pty.destroy();
});
};
Terminal.prototype.write = function(data) {