From: Yazhong Liu Date: Wed, 7 May 2014 16:05:39 +0000 (+0800) Subject: readline: fix close event of readline.Interface() X-Git-Tag: upstream/0.12.0~215 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e1aa066fe16e5feb2d5621ce0d2163703da1110c;p=platform%2Fupstream%2Fnodejs.git readline: fix close event of readline.Interface() Not removing 'end' listeners for input and output on the 'close' event resulted in an EventEmitter related memory leak. This issue also might be reproduced at: https://github.com/npm/npm/issues/5203 Signed-off-by: Trevor Norris --- diff --git a/lib/readline.js b/lib/readline.js index 1fa217c..19ef759 100644 --- a/lib/readline.js +++ b/lib/readline.js @@ -97,6 +97,13 @@ function Interface(input, output, completer, terminal) { self.close(); } + function ontermend() { + if (util.isString(self.line) && self.line.length > 0) { + self.emit('line', self.line); + } + self.close(); + } + function onkeypress(s, key) { self._ttyWrite(s, key); } @@ -121,11 +128,7 @@ function Interface(input, output, completer, terminal) { // input usually refers to stdin input.on('keypress', onkeypress); - input.on('end', function inputEnd() { - if (util.isString(self.line) && self.line.length > 0) - self.emit('line', self.line); - self.close(); - }); + input.on('end', ontermend); // Current line this.line = ''; @@ -142,6 +145,7 @@ function Interface(input, output, completer, terminal) { output.on('resize', onresize); self.once('close', function() { input.removeListener('keypress', onkeypress); + input.removeListener('end', ontermend); output.removeListener('resize', onresize); }); } diff --git a/test/simple/test-readline-interface.js b/test/simple/test-readline-interface.js index 930cf22..abd3681 100644 --- a/test/simple/test-readline-interface.js +++ b/test/simple/test-readline-interface.js @@ -35,6 +35,14 @@ FakeInput.prototype.pause = function() {}; FakeInput.prototype.write = function() {}; FakeInput.prototype.end = function() {}; +function isWarned(emitter) { + for (var name in emitter) { + var listeners = emitter[name]; + if (listeners.warned) return true; + } + return false; +} + [ true, false ].forEach(function(terminal) { var fi; var rli; @@ -262,4 +270,17 @@ FakeInput.prototype.end = function() {}; assert.equal(readline.getStringWidth('> '), 2); assert.deepEqual(fi.listeners(terminal ? 'keypress' : 'data'), []); + + // check EventEmitter memory leak + for (var i=0; i<12; i++) { + var rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); + rl.close(); + assert.equal(isWarned(process.stdin._events), false); + assert.equal(isWarned(process.stdout._events), false); + } + }); +