From ce82fa63a3e303519fee12b680b003a5f7d40d36 Mon Sep 17 00:00:00 2001 From: Brett Kiefer Date: Tue, 12 Jun 2018 11:29:57 -0400 Subject: [PATCH] net: emit 'close' when socket ends before connect Don't set `writable` to true when a socket connects if the socket is already in an ending state. In the existing code, afterConnect always set `writable` to true. This has been the case for a long time, but previous to commit 9b7a6914a7f0bd754e78b42b48c75851cfd6b3c4, the socket would still be destroyed by `destroySoon` and emit a `'close'` event. Since that commit removed this masking behavior, we have relied on maybeDestroy to destroy the socket when the readble state is ended, and that won't happen if `writable` is set to true. If the socket has `allowHalfOpen` set to true, then `destroy` will still not be called and `'close'` will not be emitted. PR-URL: https://github.com/nodejs/node/pull/21290 Fixes: https://github.com/nodejs/node/issues/21268 --- lib/net.js | 3 ++- test/parallel/test-net-socket-end-before-connect.js | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-net-socket-end-before-connect.js diff --git a/lib/net.js b/lib/net.js index 809a6f0f14582e..0f80b4189718ba 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1138,7 +1138,8 @@ function afterConnect(status, handle, req, readable, writable) { if (status === 0) { self.readable = readable; - self.writable = writable; + if (!self._writableState.ended) + self.writable = writable; self._unrefTimer(); self.emit('connect'); diff --git a/test/parallel/test-net-socket-end-before-connect.js b/test/parallel/test-net-socket-end-before-connect.js new file mode 100644 index 00000000000000..d40c90620e4153 --- /dev/null +++ b/test/parallel/test-net-socket-end-before-connect.js @@ -0,0 +1,13 @@ +'use strict'; + +const common = require('../common'); + +const net = require('net'); + +const server = net.createServer(); + +server.listen(common.mustCall(() => { + const socket = net.createConnection(server.address().port); + socket.on('close', common.mustCall(() => server.close())); + socket.end(); +}));