Skip to content

Commit 9b7a691

Browse files
committed
net: emit 'close' after 'end'
Currently the writable side of the socket is closed as soon as `UV_EOF` is read regardless of the state of the socket. This allows the handle to be closed before `'end'` is emitted and thus `'close'` can be emitted before `'end'` if the socket is paused. This commit prevents the handle from being closed until `'end'` is emitted ensuring the correct order of events. PR-URL: #19241 Fixes: #19166 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent 7455346 commit 9b7a691

12 files changed

+82
-31
lines changed

lib/net.js

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -373,8 +373,6 @@ function afterShutdown(status, handle) {
373373
if (self._readableState.ended) {
374374
debug('readableState ended, destroying');
375375
self.destroy();
376-
} else {
377-
self.once('_socketEnd', self.destroy);
378376
}
379377
}
380378

@@ -530,6 +528,11 @@ Socket.prototype.end = function(data, encoding, callback) {
530528

531529
// Called when the 'end' event is emitted.
532530
function onReadableStreamEnd() {
531+
if (!this.allowHalfOpen) {
532+
this.write = writeAfterFIN;
533+
if (this.writable)
534+
this.end();
535+
}
533536
maybeDestroy(this);
534537
}
535538

@@ -649,16 +652,6 @@ function onread(nread, buffer) {
649652
// `end` -> `close`
650653
self.push(null);
651654
self.read(0);
652-
653-
if (!self.allowHalfOpen) {
654-
self.write = writeAfterFIN;
655-
self.destroySoon();
656-
}
657-
658-
// internal end event so that we know that the actual socket
659-
// is no longer readable, and we can start the shutdown
660-
// procedure. No need to wait for all the data to be consumed.
661-
self.emit('_socketEnd');
662655
}
663656

664657

test/parallel/test-child-process-fork-net2.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ if (process.argv[2] === 'child') {
130130
console.error('[m] CLIENT: close event');
131131
disconnected += 1;
132132
});
133+
client.resume();
133134
}
134135
});
135136

test/parallel/test-http2-misbehaving-multiplex.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,5 @@ server.listen(0, () => {
6666
// either way if it is, but we don't want to die if it is.
6767
client.on('error', () => {});
6868
client.on('close', common.mustCall(() => server.close()));
69+
client.resume();
6970
});

test/parallel/test-https-client-resume.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,9 @@ server.listen(0, function() {
7979
console.log('close2');
8080
server.close();
8181
});
82+
83+
client2.resume();
8284
});
85+
86+
client1.resume();
8387
});

test/parallel/test-net-bytes-read.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const server = net.createServer((socket) => {
3232
assert.strictEqual(socket.bytesRead, prev);
3333
assert.strictEqual(big.length, prev);
3434
}));
35+
36+
socket.end();
3537
});
36-
socket.end();
3738
});

test/parallel/test-net-connect-options-path.js

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,29 @@ const CLIENT_VARIANTS = 12;
3131
});
3232

3333
// CLIENT_VARIANTS depends on the following code
34-
net.connect(serverPath, getConnectCb());
34+
net.connect(serverPath, getConnectCb()).resume();
3535
net.connect(serverPath)
36-
.on('connect', getConnectCb());
37-
net.createConnection(serverPath, getConnectCb());
36+
.on('connect', getConnectCb())
37+
.resume();
38+
net.createConnection(serverPath, getConnectCb()).resume();
3839
net.createConnection(serverPath)
39-
.on('connect', getConnectCb());
40-
new net.Socket().connect(serverPath, getConnectCb());
40+
.on('connect', getConnectCb())
41+
.resume();
42+
new net.Socket().connect(serverPath, getConnectCb()).resume();
4143
new net.Socket().connect(serverPath)
42-
.on('connect', getConnectCb());
43-
net.connect({ path: serverPath }, getConnectCb());
44+
.on('connect', getConnectCb())
45+
.resume();
46+
net.connect({ path: serverPath }, getConnectCb()).resume();
4447
net.connect({ path: serverPath })
45-
.on('connect', getConnectCb());
46-
net.createConnection({ path: serverPath }, getConnectCb());
48+
.on('connect', getConnectCb())
49+
.resume();
50+
net.createConnection({ path: serverPath }, getConnectCb()).resume();
4751
net.createConnection({ path: serverPath })
48-
.on('connect', getConnectCb());
49-
new net.Socket().connect({ path: serverPath }, getConnectCb());
52+
.on('connect', getConnectCb())
53+
.resume();
54+
new net.Socket().connect({ path: serverPath }, getConnectCb()).resume();
5055
new net.Socket().connect({ path: serverPath })
51-
.on('connect', getConnectCb());
56+
.on('connect', getConnectCb())
57+
.resume();
5258
}));
5359
}

test/parallel/test-net-connect-options-port.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,27 +102,33 @@ const net = require('net');
102102
function doConnect(args, getCb) {
103103
return [
104104
function createConnectionWithCb() {
105-
return net.createConnection.apply(net, args.concat(getCb()));
105+
return net.createConnection.apply(net, args.concat(getCb()))
106+
.resume();
106107
},
107108
function createConnectionWithoutCb() {
108109
return net.createConnection.apply(net, args)
109-
.on('connect', getCb());
110+
.on('connect', getCb())
111+
.resume();
110112
},
111113
function connectWithCb() {
112-
return net.connect.apply(net, args.concat(getCb()));
114+
return net.connect.apply(net, args.concat(getCb()))
115+
.resume();
113116
},
114117
function connectWithoutCb() {
115118
return net.connect.apply(net, args)
116-
.on('connect', getCb());
119+
.on('connect', getCb())
120+
.resume();
117121
},
118122
function socketConnectWithCb() {
119123
const socket = new net.Socket();
120-
return socket.connect.apply(socket, args.concat(getCb()));
124+
return socket.connect.apply(socket, args.concat(getCb()))
125+
.resume();
121126
},
122127
function socketConnectWithoutCb() {
123128
const socket = new net.Socket();
124129
return socket.connect.apply(socket, args)
125-
.on('connect', getCb());
130+
.on('connect', getCb())
131+
.resume();
126132
}
127133
];
128134
}

test/parallel/test-net-server-connections-child-null.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ if (process.argv[2] === 'child') {
3737
assert.strictEqual(server.connections, null);
3838
server.close();
3939
}));
40+
41+
connect.resume();
4042
}));
4143
});
4244

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
const assert = require('assert');
5+
const net = require('net');
6+
7+
const server = net.createServer();
8+
9+
server.on('connection', (socket) => {
10+
let endEmitted = false;
11+
12+
socket.once('readable', () => {
13+
setTimeout(() => {
14+
socket.read();
15+
}, common.platformTimeout(100));
16+
});
17+
socket.on('end', () => {
18+
endEmitted = true;
19+
});
20+
socket.on('close', () => {
21+
assert(endEmitted);
22+
server.close();
23+
});
24+
socket.end('foo');
25+
});
26+
27+
server.listen(common.mustCall(() => {
28+
const socket = net.createConnection(server.address().port, () => {
29+
socket.end('foo');
30+
});
31+
}));

test/parallel/test-tls-client-resume.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,9 @@ server.listen(0, function() {
7373
console.log('close2');
7474
server.close();
7575
});
76+
77+
client2.resume();
7678
});
79+
80+
client1.resume();
7781
});

test/parallel/test-tls-interleave.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const writes = [
4242
let receivedWrites = 0;
4343

4444
const server = tls.createServer(options, function(c) {
45+
c.resume();
4546
writes.forEach(function(str) {
4647
c.write(str);
4748
});

test/parallel/test-tls-tlswrap-segfault.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const server = tls.createServer(options, function(s) {
2626
const client = tls.connect(opts, function() {
2727
putImmediate(client);
2828
});
29+
client.resume();
2930
});
3031

3132
function putImmediate(client) {

0 commit comments

Comments
 (0)