diff --git a/doc/api/net.md b/doc/api/net.md index 72324760f88fc5..e8e9ea6aaa7bf9 100644 --- a/doc/api/net.md +++ b/doc/api/net.md @@ -367,6 +367,10 @@ server.listen({ }); ``` +When `exclusive` is `true` and the underlying handle is shared, it's +possible that several workers query a handle with different backlogs. +In this case, the first `backlog` passed to the master process will be used. + Starting an IPC server as root may cause the server path to be inaccessible for unprivileged users. Using `readableAll` and `writableAll` will make the server accessible for all users. diff --git a/lib/internal/cluster/round_robin_handle.js b/lib/internal/cluster/round_robin_handle.js index 492fd725c82f1d..c80ad6e58c27dd 100644 --- a/lib/internal/cluster/round_robin_handle.js +++ b/lib/internal/cluster/round_robin_handle.js @@ -13,7 +13,7 @@ const { constants } = internalBinding('tcp_wrap'); module.exports = RoundRobinHandle; -function RoundRobinHandle(key, address, { port, fd, flags }) { +function RoundRobinHandle(key, address, { port, fd, flags, backlog }) { this.key = key; this.all = new Map(); this.free = new Map(); @@ -22,16 +22,17 @@ function RoundRobinHandle(key, address, { port, fd, flags }) { this.server = net.createServer(assert.fail); if (fd >= 0) - this.server.listen({ fd }); + this.server.listen({ fd, backlog }); else if (port >= 0) { this.server.listen({ port, host: address, // Currently, net module only supports `ipv6Only` option in `flags`. ipv6Only: Boolean(flags & constants.UV_TCP_IPV6ONLY), + backlog, }); } else - this.server.listen(address); // UNIX socket path. + this.server.listen(address, backlog); // UNIX socket path. this.server.once('listening', () => { this.handle = this.server._handle; diff --git a/lib/net.js b/lib/net.js index 0b32646a43a43e..cebb7b0603daca 100644 --- a/lib/net.js +++ b/lib/net.js @@ -1343,6 +1343,7 @@ function listenInCluster(server, address, port, addressType, addressType: addressType, fd: fd, flags, + backlog, }; // Get the master's server handle, and listen on it diff --git a/test/parallel/test-cluster-net-listen-backlog.js b/test/parallel/test-cluster-net-listen-backlog.js new file mode 100644 index 00000000000000..eab734f3b6fe4f --- /dev/null +++ b/test/parallel/test-cluster-net-listen-backlog.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +// Monkey-patch `net.Server.listen` +const net = require('net'); +const cluster = require('cluster'); + +// Ensures that the `backlog` is used to create a `net.Server`. +const kExpectedBacklog = 127; +if (cluster.isMaster) { + const listen = net.Server.prototype.listen; + + net.Server.prototype.listen = common.mustCall( + function(...args) { + const options = args[0]; + if (typeof options === 'object') { + assert(options.backlog, kExpectedBacklog); + } else { + assert(args[1], kExpectedBacklog); + } + return listen.call(this, ...args); + } + ); + + const worker = cluster.fork(); + worker.on('message', () => { + worker.disconnect(); + }); +} else { + const server = net.createServer(); + + server.listen({ + host: common.localhostIPv4, + port: 0, + backlog: kExpectedBacklog, + }, common.mustCall(() => { + process.send(true); + })); +}