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 <oyydoibh@gmail.com> Reviewed-By: Ouyang Yadong <oyydoibh@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent aa684a7 commit c41e402

4 files changed

Lines changed: 54 additions & 3 deletions

File tree

‎doc/api/net.md‎

Lines changed: 4 additions & 0 deletions
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‎

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

1616
module.exports=RoundRobinHandle;
1717

18-
functionRoundRobinHandle(key,address,{ port, fd, flags }){
18+
functionRoundRobinHandle(key,address,{ port, fd, flags, backlog}){
1919
this.key=key;
2020
this.all=newSafeMap();
2121
this.free=newSafeMap();
@@ -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
elseif(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‎

Lines changed: 1 addition & 0 deletions
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
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constassert=require('assert');
5+
// Monkey-patch `net.Server.listen`
6+
constnet=require('net');
7+
constcluster=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+
constkExpectedBacklog=127;
16+
if(cluster.isMaster){
17+
constlisten=net.Server.prototype.listen;
18+
19+
net.Server.prototype.listen=common.mustCall(
20+
function(...args){
21+
constoptions=args[0];
22+
if(typeofoptions==='object'){
23+
assert(options.backlog,kExpectedBacklog);
24+
}else{
25+
assert(args[1],kExpectedBacklog);
26+
}
27+
returnlisten.call(this, ...args);
28+
}
29+
);
30+
31+
constworker=cluster.fork();
32+
worker.on('message',()=>{
33+
worker.disconnect();
34+
});
35+
}else{
36+
constserver=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)