Skip to content

Commit 62ef1e5

Browse files
committed
net: handle socket.write(cb) edge case
Make sure that when calling `write()` on a connecting socket, the callback is called if the socket is destroyed before the connection is established. Fixes: #30841
1 parent 7c7d2e8 commit 62ef1e5

File tree

4 files changed

+43
-0
lines changed

4 files changed

+43
-0
lines changed

doc/api/errors.md

+8
Original file line numberDiff line numberDiff line change
@@ -2573,6 +2573,13 @@ could not be determined.
25732573

25742574
An attempt was made to operate on an already closed socket.
25752575

2576+
<a id="ERR_SOCKET_CLOSED_BEFORE_CONNECTION"></a>
2577+
2578+
### `ERR_SOCKET_CLOSED_BEFORE_CONNECTION`
2579+
2580+
When calling [`net.Socket.write()`][] on a connecting socket and the socket was
2581+
closed before the connection was established.
2582+
25762583
<a id="ERR_SOCKET_DGRAM_IS_CONNECTED"></a>
25772584

25782585
### `ERR_SOCKET_DGRAM_IS_CONNECTED`
@@ -3586,6 +3593,7 @@ The native call from `process.cpuUsage` could not be processed.
35863593
[`http`]: http.md
35873594
[`https`]: https.md
35883595
[`libuv Error handling`]: https://docs.libuv.org/en/v1.x/errors.html
3596+
[`net.Socket.write()`]: net.md#socketwritedata-encoding-callback
35893597
[`net`]: net.md
35903598
[`new URL(input)`]: url.md#new-urlinput-base
35913599
[`new URLSearchParams(iterable)`]: url.md#new-urlsearchparamsiterable

lib/internal/errors.js

+3
Original file line numberDiff line numberDiff line change
@@ -1566,6 +1566,9 @@ E('ERR_SOCKET_BUFFER_SIZE',
15661566
'Could not get or set buffer size',
15671567
SystemError);
15681568
E('ERR_SOCKET_CLOSED', 'Socket is closed', Error);
1569+
E('ERR_SOCKET_CLOSED_BEFORE_CONNECTION',
1570+
'Socket closed before the connection was established',
1571+
Error);
15691572
E('ERR_SOCKET_DGRAM_IS_CONNECTED', 'Already connected', Error);
15701573
E('ERR_SOCKET_DGRAM_NOT_CONNECTED', 'Not connected', Error);
15711574
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error);

lib/net.js

+6
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const {
9898
ERR_SERVER_ALREADY_LISTEN,
9999
ERR_SERVER_NOT_RUNNING,
100100
ERR_SOCKET_CLOSED,
101+
ERR_SOCKET_CLOSED_BEFORE_CONNECTION,
101102
ERR_MISSING_ARGS,
102103
},
103104
aggregateErrors,
@@ -896,8 +897,13 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
896897
this._pendingData = data;
897898
this._pendingEncoding = encoding;
898899
this.once('connect', function connect() {
900+
this.off('close', onClose);
899901
this._writeGeneric(writev, data, encoding, cb);
900902
});
903+
function onClose() {
904+
cb(new ERR_SOCKET_CLOSED_BEFORE_CONNECTION());
905+
}
906+
this.once('close', onClose);
901907
return;
902908
}
903909
this._pendingData = null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const net = require('net');
6+
7+
const server = net.createServer();
8+
server.listen(0, common.mustCall(() => {
9+
const socket = new net.Socket();
10+
11+
socket.on('connect', common.mustNotCall());
12+
13+
socket.connect({
14+
port: server.address().port,
15+
});
16+
17+
assert(socket.connecting);
18+
19+
socket.write('foo', common.expectsError({
20+
code: 'ERR_SOCKET_CLOSED_BEFORE_CONNECTION',
21+
name: 'Error'
22+
}));
23+
24+
socket.destroy();
25+
server.close();
26+
}));

0 commit comments

Comments
 (0)