Skip to content

Commit 5e339ec

Browse files
committed
fix(cluster): respect the backlog from workers
Currently, the master process would ignore `backlog` from worker processes and use the default value instead. This commit will respect the first `backlog` passed to the master process for a specific handle. Refs: #4056
1 parent 6726246 commit 5e339ec

File tree

4 files changed

+51
-3
lines changed

4 files changed

+51
-3
lines changed

doc/api/net.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ server.listen({
367367
});
368368
```
369369

370+
When `exclusive` is `true` and the underlying handle is shared, it's
371+
possible that several workers query a handle with different backlogs.
372+
In this case, the first `backlog` passed to the master process will be used.
373+
370374
Starting an IPC server as root may cause the server path to be inaccessible for
371375
unprivileged users. Using `readableAll` and `writableAll` will make the server
372376
accessible for all users.

lib/internal/cluster/round_robin_handle.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const { constants } = internalBinding('tcp_wrap');
1313

1414
module.exports = RoundRobinHandle;
1515

16-
function RoundRobinHandle(key, address, { port, fd, flags }) {
16+
function RoundRobinHandle(key, address, { port, fd, flags, backlog }) {
1717
this.key = key;
1818
this.all = new Map();
1919
this.free = new Map();
@@ -22,16 +22,17 @@ function RoundRobinHandle(key, address, { port, fd, flags }) {
2222
this.server = net.createServer(assert.fail);
2323

2424
if (fd >= 0)
25-
this.server.listen({ fd });
25+
this.server.listen({ fd, backlog });
2626
else if (port >= 0) {
2727
this.server.listen({
2828
port,
2929
host: address,
3030
// Currently, net module only supports `ipv6Only` option in `flags`.
3131
ipv6Only: Boolean(flags & constants.UV_TCP_IPV6ONLY),
32+
backlog,
3233
});
3334
} else
34-
this.server.listen(address); // UNIX socket path.
35+
this.server.listen(address, backlog); // UNIX socket path.
3536

3637
this.server.once('listening', () => {
3738
this.handle = this.server._handle;

lib/net.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,7 @@ function listenInCluster(server, address, port, addressType,
13431343
addressType: addressType,
13441344
fd: fd,
13451345
flags,
1346+
backlog,
13461347
};
13471348

13481349
// Get the master's server handle, and listen on it
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const Countdown = require('../common/countdown');
5+
const assert = require('assert');
6+
// Monkey-patch `net.Server._listen2`
7+
const net = require('net');
8+
const cluster = require('cluster');
9+
10+
// Ensures that the `backlog` is used to create a `net.Server`.
11+
const kExpectedBacklog = 127;
12+
if (cluster.isMaster) {
13+
let worker
14+
15+
const nativeListen = net.Server.prototype._listen2;
16+
const countdown = new Countdown(2, () => {
17+
worker.disconnect();
18+
});
19+
20+
net.Server.prototype._listen2 = common.mustCall(
21+
function(address, port, addressType, backlog, fd, flags) {
22+
assert(backlog, kExpectedBacklog);
23+
countdown.dec();
24+
return nativeListen.call(this, address, port, addressType, backlog, fd, flags);
25+
}
26+
);
27+
28+
worker = cluster.fork();
29+
worker.on('message', () => {
30+
countdown.dec();
31+
});
32+
} else {
33+
const server = net.createServer()
34+
35+
server.listen({
36+
host: common.localhostIPv4,
37+
port: 0,
38+
backlog: kExpectedBacklog,
39+
}, common.mustCall(() => {
40+
process.send(true);
41+
}));
42+
}

0 commit comments

Comments
 (0)