Skip to content

Commit c41e402

Browse files
eladnavaoyyd
authored andcommitted
cluster: respect listen backlog set by workers
PR-URL: #41623 Co-authored-by: Ouyang Yadong <[email protected]> Reviewed-By: Ouyang Yadong <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent aa684a7 commit c41e402

File tree

4 files changed

+54
-3
lines changed

4 files changed

+54
-3
lines changed

doc/api/net.md

+4
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,10 @@ server.listen({
464464
});
465465
```
466466

467+
When `exclusive` is `true` and the underlying handle is shared, it is
468+
possible that several workers query a handle with different backlogs.
469+
In this case, the first `backlog` passed to the master process will be used.
470+
467471
Starting an IPC server as root may cause the server path to be inaccessible for
468472
unprivileged users. Using `readableAll` and `writableAll` will make the server
469473
accessible for all users.

lib/internal/cluster/round_robin_handle.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const { constants } = internalBinding('tcp_wrap');
1515

1616
module.exports = RoundRobinHandle;
1717

18-
function RoundRobinHandle(key, address, { port, fd, flags }) {
18+
function RoundRobinHandle(key, address, { port, fd, flags, backlog }) {
1919
this.key = key;
2020
this.all = new SafeMap();
2121
this.free = new SafeMap();
@@ -24,16 +24,17 @@ function RoundRobinHandle(key, address, { port, fd, flags }) {
2424
this.server = net.createServer(assert.fail);
2525

2626
if (fd >= 0)
27-
this.server.listen({ fd });
27+
this.server.listen({ fd, backlog });
2828
else if (port >= 0) {
2929
this.server.listen({
3030
port,
3131
host: address,
3232
// Currently, net module only supports `ipv6Only` option in `flags`.
3333
ipv6Only: Boolean(flags & constants.UV_TCP_IPV6ONLY),
34+
backlog,
3435
});
3536
} else
36-
this.server.listen(address); // UNIX socket path.
37+
this.server.listen(address, backlog); // UNIX socket path.
3738

3839
this.server.once('listening', () => {
3940
this.handle = this.server._handle;

lib/net.js

+1
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@ function listenInCluster(server, address, port, addressType,
13861386
addressType: addressType,
13871387
fd: fd,
13881388
flags,
1389+
backlog,
13891390
};
13901391

13911392
// Get the primary's server handle, and listen on it
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
// Monkey-patch `net.Server.listen`
6+
const net = require('net');
7+
const cluster = require('cluster');
8+
9+
// Force round-robin scheduling policy
10+
// as Windows defaults to SCHED_NONE
11+
// https://nodejs.org/docs/latest/api/cluster.html#clusterschedulingpolicy
12+
cluster.schedulingPolicy = cluster.SCHED_RR;
13+
14+
// Ensures that the `backlog` is used to create a `net.Server`.
15+
const kExpectedBacklog = 127;
16+
if (cluster.isMaster) {
17+
const listen = net.Server.prototype.listen;
18+
19+
net.Server.prototype.listen = common.mustCall(
20+
function(...args) {
21+
const options = args[0];
22+
if (typeof options === 'object') {
23+
assert(options.backlog, kExpectedBacklog);
24+
} else {
25+
assert(args[1], kExpectedBacklog);
26+
}
27+
return listen.call(this, ...args);
28+
}
29+
);
30+
31+
const worker = cluster.fork();
32+
worker.on('message', () => {
33+
worker.disconnect();
34+
});
35+
} else {
36+
const server = net.createServer();
37+
38+
server.listen({
39+
host: common.localhostIPv4,
40+
port: 0,
41+
backlog: kExpectedBacklog,
42+
}, common.mustCall(() => {
43+
process.send(true);
44+
}));
45+
}

0 commit comments

Comments
 (0)