cluster: resolve relative unix socket paths
Relative unix sockets paths were previously interpreted relative to the master's CWD, which was inconsistent with non-cluster behavior. A test case has been added as well. PR-URL: https://github.com/nodejs/node/pull/16749 Fixes: https://github.com/nodejs/node/issues/16387 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
This commit is contained in:
parent
f878f9414e
commit
4e2e7d11e1
@ -1,6 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const path = require('path');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const Worker = require('internal/cluster/worker');
|
const Worker = require('internal/cluster/worker');
|
||||||
const { internal, sendHelper } = require('internal/cluster/utils');
|
const { internal, sendHelper } = require('internal/cluster/utils');
|
||||||
@ -48,7 +49,14 @@ cluster._setupWorker = function() {
|
|||||||
|
|
||||||
// obj is a net#Server or a dgram#Socket object.
|
// obj is a net#Server or a dgram#Socket object.
|
||||||
cluster._getServer = function(obj, options, cb) {
|
cluster._getServer = function(obj, options, cb) {
|
||||||
const indexesKey = [options.address,
|
let address = options.address;
|
||||||
|
|
||||||
|
// Resolve unix socket paths to absolute paths
|
||||||
|
if (options.port < 0 && typeof address === 'string' &&
|
||||||
|
process.platform !== 'win32')
|
||||||
|
address = path.resolve(address);
|
||||||
|
|
||||||
|
const indexesKey = [address,
|
||||||
options.port,
|
options.port,
|
||||||
options.addressType,
|
options.addressType,
|
||||||
options.fd ].join(':');
|
options.fd ].join(':');
|
||||||
@ -64,6 +72,8 @@ cluster._getServer = function(obj, options, cb) {
|
|||||||
data: null
|
data: null
|
||||||
}, options);
|
}, options);
|
||||||
|
|
||||||
|
message.address = address;
|
||||||
|
|
||||||
// Set custom data on handle (i.e. tls tickets key)
|
// Set custom data on handle (i.e. tls tickets key)
|
||||||
if (obj._getServerData)
|
if (obj._getServerData)
|
||||||
message.data = obj._getServerData();
|
message.data = obj._getServerData();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
const { fork } = require('child_process');
|
const { fork } = require('child_process');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
const path = require('path');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const RoundRobinHandle = require('internal/cluster/round_robin_handle');
|
const RoundRobinHandle = require('internal/cluster/round_robin_handle');
|
||||||
const SharedHandle = require('internal/cluster/shared_handle');
|
const SharedHandle = require('internal/cluster/shared_handle');
|
||||||
@ -276,6 +277,18 @@ function queryServer(worker, message) {
|
|||||||
var handle = handles[key];
|
var handle = handles[key];
|
||||||
|
|
||||||
if (handle === undefined) {
|
if (handle === undefined) {
|
||||||
|
let address = message.address;
|
||||||
|
|
||||||
|
// Find shortest path for unix sockets because of the ~100 byte limit
|
||||||
|
if (message.port < 0 && typeof address === 'string' &&
|
||||||
|
process.platform !== 'win32') {
|
||||||
|
|
||||||
|
address = path.relative(process.cwd(), address);
|
||||||
|
|
||||||
|
if (message.address.length < address.length)
|
||||||
|
address = message.address;
|
||||||
|
}
|
||||||
|
|
||||||
var constructor = RoundRobinHandle;
|
var constructor = RoundRobinHandle;
|
||||||
// UDP is exempt from round-robin connection balancing for what should
|
// UDP is exempt from round-robin connection balancing for what should
|
||||||
// be obvious reasons: it's connectionless. There is nothing to send to
|
// be obvious reasons: it's connectionless. There is nothing to send to
|
||||||
@ -287,7 +300,7 @@ function queryServer(worker, message) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handles[key] = handle = new constructor(key,
|
handles[key] = handle = new constructor(key,
|
||||||
message.address,
|
address,
|
||||||
message.port,
|
message.port,
|
||||||
message.addressType,
|
message.addressType,
|
||||||
message.fd,
|
message.fd,
|
||||||
|
44
test/parallel/test-cluster-net-listen-relative-path.js
Normal file
44
test/parallel/test-cluster-net-listen-relative-path.js
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const cluster = require('cluster');
|
||||||
|
const net = require('net');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
if (common.isWindows)
|
||||||
|
common.skip('On Windows named pipes live in their own ' +
|
||||||
|
'filesystem and don\'t have a ~100 byte limit');
|
||||||
|
|
||||||
|
// Choose a socket name such that the absolute path would exceed 100 bytes.
|
||||||
|
const socketDir = './unix-socket-dir';
|
||||||
|
const socketName = 'A'.repeat(100 - socketDir.length - 1);
|
||||||
|
|
||||||
|
// Make sure we're not in a weird environment
|
||||||
|
assert.strictEqual(path.resolve(socketDir, socketName).length > 100, true,
|
||||||
|
'absolute socket path should be longer than 100 bytes');
|
||||||
|
|
||||||
|
if (cluster.isMaster) {
|
||||||
|
// ensure that the worker exits peacefully
|
||||||
|
process.chdir(common.tmpDir);
|
||||||
|
fs.mkdirSync(socketDir);
|
||||||
|
cluster.fork().on('exit', common.mustCall(function(statusCode) {
|
||||||
|
assert.strictEqual(statusCode, 0);
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
fs.existsSync(path.join(socketDir, socketName)), false,
|
||||||
|
'Socket should be removed when the worker exits');
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
process.chdir(socketDir);
|
||||||
|
|
||||||
|
const server = net.createServer(common.mustNotCall());
|
||||||
|
|
||||||
|
server.listen(socketName, common.mustCall(function() {
|
||||||
|
assert.strictEqual(
|
||||||
|
fs.existsSync(socketName), true,
|
||||||
|
'Socket created in CWD');
|
||||||
|
|
||||||
|
process.disconnect();
|
||||||
|
}));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user