From 75a0cf970fb48440a93a62796ab1f128fcbe7d76 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 2 May 2011 12:13:06 -0700 Subject: [PATCH] cleartextstream.destroy() should destroy socket. This fixes a critical bug see in MJR's production. Very difficult to build a test case. Sometimes HTTPS server gets sockets that are hanging in a half-duplex state. --- lib/stream.js | 22 ++++++++++++++++++++-- lib/tls.js | 5 ----- test/simple/test-https-eof-for-eom.js | 2 +- test/simple/test-stream-pipe-cleanup.js | 4 ++++ 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lib/stream.js b/lib/stream.js index ca7fc28c02..a5b797482e 100644 --- a/lib/stream.js +++ b/lib/stream.js @@ -53,7 +53,7 @@ Stream.prototype.pipe = function(dest, options) { dest._pipeCount++; source.on('end', onend); - source.on('close', onend); + source.on('close', onclose); } var didOnEnd = false; @@ -74,6 +74,24 @@ Stream.prototype.pipe = function(dest, options) { dest.end(); } + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + dest._pipeCount--; + + // remove the listeners + cleanup(); + + if (dest._pipeCount > 0) { + // waiting for other incoming streams to end. + return; + } + + dest.destroy(); + } + // don't leave dangling pipes when there are errors. function onerror(er) { cleanup(); @@ -117,7 +135,7 @@ Stream.prototype.pipe = function(dest, options) { dest.removeListener('drain', ondrain); source.removeListener('end', onend); - source.removeListener('close', onend); + source.removeListener('close', onclose); dest.removeListener('pause', onpause); dest.removeListener('resume', onresume); diff --git a/lib/tls.js b/lib/tls.js index b34ed95204..a2496b2383 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -608,12 +608,7 @@ SecurePair.prototype._destroy = function() { self.cleartext.writable = self.cleartext.readable = false; process.nextTick(function() { - self.encrypted.emit('end'); - if (self.encrypted.onend) self.encrypted.onend(); self.encrypted.emit('close'); - - self.cleartext.emit('end'); - if (self.cleartext.onend) self.cleartext.onend(); self.cleartext.emit('close'); }); } diff --git a/test/simple/test-https-eof-for-eom.js b/test/simple/test-https-eof-for-eom.js index 19f6520a6d..e043c5df8a 100644 --- a/test/simple/test-https-eof-for-eom.js +++ b/test/simple/test-https-eof-for-eom.js @@ -83,7 +83,7 @@ server.listen(common.PORT, function() { bodyBuffer += s; }); - res.on('end', function() { + res.on('close', function() { console.log('5) Client got "end" event.'); gotEnd = true; }); diff --git a/test/simple/test-stream-pipe-cleanup.js b/test/simple/test-stream-pipe-cleanup.js index 32ecd153dc..ba3ffe128c 100644 --- a/test/simple/test-stream-pipe-cleanup.js +++ b/test/simple/test-stream-pipe-cleanup.js @@ -36,6 +36,10 @@ Writable.prototype.end = function () { this.endCalls++; } +Writable.prototype.destroy = function () { + this.endCalls++; +} + function Readable () { this.readable = true; stream.Stream.call(this);