Skip to content

Commit 9c7a6df

Browse files
committed
tls: handle cases where the raw socket is destroyed
Ensure that the `'close'` event is emitted on a `TLSSocket` when it is created from an existing raw `net.Socket` and the raw socket is not closed cleanly (destroyed). Refs: #49902 (comment) Fixes: #49902
1 parent 7b624c3 commit 9c7a6df

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

lib/_tls_wrap.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -657,10 +657,20 @@ tls_wrap.TLSWrap.prototype.close = function close(cb) {
657657
cb();
658658
};
659659

660-
if (this._parentWrap && this._parentWrap._handle === this._parent) {
661-
this._parentWrap.once('close', done);
662-
return this._parentWrap.destroy();
660+
if (this._parentWrap) {
661+
if (this._parentWrap._handle === null) {
662+
// The socket handle was already closed.
663+
done();
664+
return;
665+
}
666+
667+
if (this._parentWrap._handle === this._parent) {
668+
this._parentWrap.once('close', done);
669+
this._parentWrap.destroy();
670+
return;
671+
}
663672
}
673+
664674
return this._parent.close(done);
665675
};
666676

test/parallel/test-tls-socket-close.js

+24-11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ if (!common.hasCrypto)
66
const assert = require('assert');
77
const tls = require('tls');
88
const net = require('net');
9+
const Countdown = require('../common/countdown');
910
const fixtures = require('../common/fixtures');
1011

1112
const key = fixtures.readKey('agent2-key.pem');
@@ -14,19 +15,28 @@ const cert = fixtures.readKey('agent2-cert.pem');
1415
let serverTlsSocket;
1516
const tlsServer = tls.createServer({ cert, key }, (socket) => {
1617
serverTlsSocket = socket;
18+
socket.on('close', dec);
1719
});
1820

1921
// A plain net server, that manually passes connections to the TLS
20-
// server to be upgraded
22+
// server to be upgraded.
2123
let netSocket;
24+
let netSocketCloseEmitted = false;
2225
const netServer = net.createServer((socket) => {
23-
tlsServer.emit('connection', socket);
24-
2526
netSocket = socket;
26-
}).listen(0, common.mustCall(function() {
27+
tlsServer.emit('connection', socket);
28+
socket.on('close', () => {
29+
netSocketCloseEmitted = true;
30+
assert.strictEqual(serverTlsSocket.destroyed, true);
31+
});
32+
}).listen(0, common.mustCall(() => {
2733
connectClient(netServer);
2834
}));
2935

36+
const countdown = new Countdown(2, () => {
37+
netServer.close();
38+
});
39+
3040
// A client that connects, sends one message, and closes the raw connection:
3141
function connectClient(server) {
3242
const clientTlsSocket = tls.connect({
@@ -41,18 +51,21 @@ function connectClient(server) {
4151
assert(serverTlsSocket);
4252

4353
netSocket.destroy();
54+
assert.strictEqual(netSocket.destroyed, true);
4455

4556
setImmediate(() => {
46-
assert.strictEqual(netSocket.destroyed, true);
47-
57+
assert.strictEqual(netSocketCloseEmitted, false);
58+
assert.strictEqual(serverTlsSocket.destroyed, false);
4859
setImmediate(() => {
49-
assert.strictEqual(clientTlsSocket.destroyed, true);
50-
assert.strictEqual(serverTlsSocket.destroyed, true);
51-
52-
tlsServer.close();
53-
netServer.close();
60+
assert.strictEqual(netSocketCloseEmitted, true);
5461
});
5562
});
5663
}));
5764
}));
65+
66+
clientTlsSocket.on('close', dec);
67+
}
68+
69+
function dec() {
70+
countdown.dec();
5871
}

0 commit comments

Comments
 (0)