Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

tls: Closing parent socket also closes the tls sock #25642

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/_tls_wrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ function onocspresponse(resp) {
function TLSSocket(socket, options) {
// Disallow wrapping TLSSocket in TLSSocket
assert(!(socket instanceof TLSSocket));
var self = this;

net.Socket.call(this, {
handle: socket && socket._handle,
Expand All @@ -238,6 +239,9 @@ function TLSSocket(socket, options) {

if (socket) {
this._parent = socket;
socket._destroy = function(exception) {
self._destroy(exception);
};
// To prevent assertion in afterConnect()
this._connecting = socket._connecting;
}
Expand Down
18 changes: 10 additions & 8 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -468,12 +468,10 @@ Socket.prototype._destroy = function(exception, cb) {
return;
}

self._connecting = false;

this.readable = this.writable = false;

for (var s = this; s !== null; s = s._parent)
for (var s = this; s !== null; s = s._parent) {
timers.unenroll(s);
s._connecting = s.readable = s.writable = false;
}

debug('close');
if (this._handle) {
Expand All @@ -482,16 +480,20 @@ Socket.prototype._destroy = function(exception, cb) {
var isException = exception ? true : false;
this._handle.close(function() {
debug('emit close');
self.emit('close', isException);
for (var s = self; s !== null; s = s._parent)
s.emit('close', isException);
});
this._handle.onread = noop;
this._handle = null;
for (var s = this; s !== null; s = s._parent)
s._handle = null;
}

// we set destroyed to true before firing error callbacks in order
// to make it re-entrance safe in case Socket.prototype.destroy()
// is called within callbacks
this.destroyed = true;
for (var s = this; s !== null; s = s._parent)
s.destroyed = true;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be moved to the loop above this.


fireErrorCallbacks();

if (this.server) {
Expand Down
55 changes: 55 additions & 0 deletions test/simple/test-tls-destroy-socket.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
if (!process.versions.openssl) {
console.error('Skipping because node compiled without OpenSSL.');
process.exit(0);
}

var common = require('../common');
var assert = require('assert');
var tls = require('tls');
var fs = require('fs');

var options = {
key: fs.readFileSync(common.fixturesDir + '/keys/agent2-key.pem'),
cert: fs.readFileSync(common.fixturesDir + '/keys/agent2-cert.pem')
};

var normalSock = null;
var hasError = false;
var tlsCloseCount = 0;
var sockCloseCount = 0;

var server = tls.createServer(options, function(secureSock) {
secureSock.on('error', function() {
hasError = true;
});
secureSock.on('close', function() {
tlsCloseCount++;
});
normalSock.on('close', function() {
sockCloseCount++;
});

normalSock.destroy();
secureSock.write('Test!', function(err) {
assert(err);
});
});

server.on('connection', function(sock) {
normalSock = sock;
});

server.listen(common.PORT, function() {
var c = tls.connect(common.PORT, {rejectUnauthorized: false});
c.on('error', function() {}); // ignore socket hangup error

c.on('end', function() {
server.close();
});

process.on('exit', function() {
assert(hasError);
assert.equal(tlsCloseCount, 1);
assert.equal(sockCloseCount, 1);
});
});