Skip to content

Commit 3ca99ea

Browse files
committed
net: add support for finished after .destroy()
Calling `finished(socket, cb)` would previously not invoked the callback if the socket was already detroyed.
1 parent 7303afb commit 3ca99ea

File tree

4 files changed

+48
-7
lines changed

4 files changed

+48
-7
lines changed

lib/_http_incoming.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,8 @@ IncomingMessage.prototype._destroy = function _destroy(err, cb) {
169169
this.emit('aborted');
170170
}
171171

172-
// If aborted and the underlying socket is not already destroyed,
173-
// destroy it.
174-
// We have to check if the socket is already destroyed because finished
175-
// does not call the callback when this methdod is invoked from `_http_client`
176-
// in `test/parallel/test-http-client-spurious-aborted.js`
177-
if (this.socket && !this.socket.destroyed && this.aborted) {
172+
// If aborted destroy socket.
173+
if (this.socket && this.aborted) {
178174
this.socket.destroy(err);
179175
const cleanup = finished(this.socket, (e) => {
180176
cleanup();

lib/internal/streams/end-of-stream.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ const {
99
} = require('internal/errors').codes;
1010
const { once } = require('internal/util');
1111

12+
function isSocket(stream) {
13+
return (
14+
typeof stream.connect === 'function' &&
15+
typeof stream.setNoDelay === 'function' &&
16+
typeof stream.setKeepAlive === 'function'
17+
);
18+
}
19+
1220
function isRequest(stream) {
1321
return stream.setHeader && typeof stream.abort === 'function';
1422
}
@@ -75,7 +83,7 @@ function eos(stream, options, callback) {
7583
let willEmitClose = (
7684
state &&
7785
state.autoDestroy &&
78-
state.emitClose &&
86+
(state.emitClose || isSocket(stream)) &&
7987
state.closed === false &&
8088
isReadable(stream) === readable &&
8189
isWritable(stream) === writable

lib/net.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -663,6 +663,12 @@ Socket.prototype._destroy = function(exception, cb) {
663663

664664
this._handle.close(() => {
665665
debug('emit close');
666+
if (this._writableState) {
667+
this._writableState.closed = true;
668+
}
669+
if (this._readableState) {
670+
this._readableState.closed = true;
671+
}
666672
this.emit('close', isException);
667673
});
668674
this._handle.onread = noop;
@@ -1633,6 +1639,12 @@ Server.prototype._emitCloseIfDrained = function() {
16331639

16341640
function emitCloseNT(self) {
16351641
debug('SERVER: emit close');
1642+
if (self._writableState) {
1643+
self._writableState.closed = true;
1644+
}
1645+
if (self._readableState) {
1646+
self._readableState.closed = true;
1647+
}
16361648
self.emit('close');
16371649
}
16381650

test/parallel/test-net-finished.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
'use strict';
2+
const common = require('../common');
3+
const net = require('net');
4+
const { finished } = require('stream');
5+
6+
const server = net.createServer(function(con) {
7+
con.on('close', common.mustCall());
8+
});
9+
10+
server.listen(0, common.mustCall(function() {
11+
const con = net.connect({
12+
port: this.address().port
13+
})
14+
.on('connect', () => {
15+
finished(con, common.mustCall());
16+
con.destroy();
17+
finished(con, common.mustCall());
18+
con.on('close', common.mustCall(() => {
19+
finished(con, common.mustCall(() => {
20+
server.close();
21+
}));
22+
}));
23+
})
24+
.end();
25+
}));

0 commit comments

Comments
 (0)