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>
pull/18103/merge
laino 2018-01-08 21:05:33 +01:00 committed by Joyee Cheung
parent f878f9414e
commit 4e2e7d11e1
No known key found for this signature in database
GPG Key ID: F586868AAD831D0C
3 changed files with 69 additions and 2 deletions

View File

@ -1,6 +1,7 @@
'use strict';
const assert = require('assert');
const util = require('util');
const path = require('path');
const EventEmitter = require('events');
const Worker = require('internal/cluster/worker');
const { internal, sendHelper } = require('internal/cluster/utils');
@ -48,7 +49,14 @@ cluster._setupWorker = function() {
// obj is a net#Server or a dgram#Socket object.
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.addressType,
options.fd ].join(':');
@ -64,6 +72,8 @@ cluster._getServer = function(obj, options, cb) {
data: null
}, options);
message.address = address;
// Set custom data on handle (i.e. tls tickets key)
if (obj._getServerData)
message.data = obj._getServerData();

View File

@ -2,6 +2,7 @@
const assert = require('assert');
const { fork } = require('child_process');
const util = require('util');
const path = require('path');
const EventEmitter = require('events');
const RoundRobinHandle = require('internal/cluster/round_robin_handle');
const SharedHandle = require('internal/cluster/shared_handle');
@ -276,6 +277,18 @@ function queryServer(worker, message) {
var handle = handles[key];
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;
// UDP is exempt from round-robin connection balancing for what should
// 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,
message.address,
address,
message.port,
message.addressType,
message.fd,

View 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();
}));
}