cluster: overriding inspector port
Added an option to override inspector port for workers using `settings.inspectPort` will override default port incrementing behavior. Also, using this option allows to set 0 port for the whole cluster. PR-URL: https://github.com/nodejs/node/pull/14140 Fixes: https://github.com/nodejs/node/issues/8495 Fixes: https://github.com/nodejs/node/issues/12941 Refs: https://github.com/nodejs/node/pull/9659 Refs: https://github.com/nodejs/node/pull/13761 Reviewed-By: Refael Ackermann <refack@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
This commit is contained in:
parent
592b0ed431
commit
b4300536f5
@ -712,6 +712,9 @@ changes:
|
||||
`'ipc'` entry. When this option is provided, it overrides `silent`.
|
||||
* `uid` {number} Sets the user identity of the process. (See setuid(2).)
|
||||
* `gid` {number} Sets the group identity of the process. (See setgid(2).)
|
||||
* `inspectPort` {number|function} Sets inspector port of worker.
|
||||
Accepts number, or function that evaluates to number. By default
|
||||
each worker gets port, incremented from master's `process.debugPort`.
|
||||
|
||||
After calling `.setupMaster()` (or `.fork()`) this settings object will contain
|
||||
the settings, including the default values.
|
||||
|
@ -12,6 +12,7 @@ const cluster = new EventEmitter();
|
||||
const intercom = new EventEmitter();
|
||||
const SCHED_NONE = 1;
|
||||
const SCHED_RR = 2;
|
||||
const {isLegalPort} = require('internal/net');
|
||||
|
||||
module.exports = cluster;
|
||||
|
||||
@ -104,8 +105,23 @@ function createWorkerProcess(id, env) {
|
||||
workerEnv.NODE_UNIQUE_ID = '' + id;
|
||||
|
||||
if (execArgv.some((arg) => arg.match(debugArgRegex))) {
|
||||
execArgv.push(`--inspect-port=${process.debugPort + debugPortOffset}`);
|
||||
debugPortOffset++;
|
||||
let inspectPort;
|
||||
if ('inspectPort' in cluster.settings) {
|
||||
if (typeof cluster.settings.inspectPort === 'function')
|
||||
inspectPort = cluster.settings.inspectPort();
|
||||
else
|
||||
inspectPort = cluster.settings.inspectPort;
|
||||
|
||||
if (!isLegalPort(inspectPort)) {
|
||||
throw new TypeError('cluster.settings.inspectPort' +
|
||||
' is invalid');
|
||||
}
|
||||
} else {
|
||||
inspectPort = process.debugPort + debugPortOffset;
|
||||
debugPortOffset++;
|
||||
}
|
||||
|
||||
execArgv.push(`--inspect-port=${inspectPort}`);
|
||||
}
|
||||
|
||||
return fork(cluster.settings.exec, cluster.settings.args, {
|
||||
|
@ -18,7 +18,7 @@ let offset = 0;
|
||||
*/
|
||||
|
||||
function testRunnerMain() {
|
||||
spawnMaster({
|
||||
let defaultPortCase = spawnMaster({
|
||||
execArgv: ['--inspect'],
|
||||
workers: [{expectedPort: 9230}]
|
||||
});
|
||||
@ -77,42 +77,251 @@ function testRunnerMain() {
|
||||
workers: [{expectedPort: port + 1, expectedHost: '::1'}]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// These tests check that setting inspectPort in cluster.settings
|
||||
// would take effect and override port incrementing behavior
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: port + 2},
|
||||
workers: [{expectedPort: port + 2}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'addTwo'},
|
||||
workers: [
|
||||
{expectedPort: port + 2},
|
||||
{expectedPort: port + 4}
|
||||
]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'string'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'null'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'bignumber'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'negativenumber'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'bignumberfunc'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 'strfunc'},
|
||||
workers: [{}]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [],
|
||||
clusterSettings: {inspectPort: port, execArgv: ['--inspect']},
|
||||
workers: [
|
||||
{expectedPort: port}
|
||||
]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [`--inspect=${port}`],
|
||||
clusterSettings: {inspectPort: 0},
|
||||
workers: [
|
||||
{expectedInitialPort: 0},
|
||||
{expectedInitialPort: 0},
|
||||
{expectedInitialPort: 0}
|
||||
]
|
||||
});
|
||||
|
||||
port = debuggerPort + offset++ * 5;
|
||||
|
||||
spawnMaster({
|
||||
execArgv: [],
|
||||
clusterSettings: {inspectPort: 0},
|
||||
workers: [
|
||||
{expectedInitialPort: 0},
|
||||
{expectedInitialPort: 0},
|
||||
{expectedInitialPort: 0}
|
||||
]
|
||||
});
|
||||
|
||||
defaultPortCase.then(() => {
|
||||
port = debuggerPort + offset++ * 5;
|
||||
defaultPortCase = spawnMaster({
|
||||
execArgv: ['--inspect'],
|
||||
clusterSettings: {inspectPort: port + 2},
|
||||
workers: [
|
||||
{expectedInitialPort: port + 2}
|
||||
]
|
||||
});
|
||||
});
|
||||
}
|
||||
function masterProcessMain() {
|
||||
const workers = JSON.parse(process.env.workers);
|
||||
const clusterSettings = JSON.parse(process.env.clusterSettings);
|
||||
let debugPort = process.debugPort;
|
||||
|
||||
for (const worker of workers) {
|
||||
cluster.fork({
|
||||
expectedPort: worker.expectedPort,
|
||||
expectedHost: worker.expectedHost
|
||||
}).on('exit', common.mustCall(checkExitCode));
|
||||
const params = {};
|
||||
|
||||
if (worker.expectedPort) {
|
||||
params.expectedPort = worker.expectedPort;
|
||||
}
|
||||
|
||||
if (worker.expectedInitialPort) {
|
||||
params.expectedInitialPort = worker.expectedInitialPort;
|
||||
}
|
||||
|
||||
if (worker.expectedHost) {
|
||||
params.expectedHost = worker.expectedHost;
|
||||
}
|
||||
|
||||
if (clusterSettings) {
|
||||
if (clusterSettings.inspectPort === 'addTwo') {
|
||||
clusterSettings.inspectPort = common.mustCall(
|
||||
() => { return debugPort += 2; },
|
||||
workers.length
|
||||
);
|
||||
} else if (clusterSettings.inspectPort === 'string') {
|
||||
clusterSettings.inspectPort = 'string';
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
} else if (clusterSettings.inspectPort === 'null') {
|
||||
clusterSettings.inspectPort = null;
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
} else if (clusterSettings.inspectPort === 'bignumber') {
|
||||
clusterSettings.inspectPort = 1293812;
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
} else if (clusterSettings.inspectPort === 'negativenumber') {
|
||||
clusterSettings.inspectPort = -9776;
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
} else if (clusterSettings.inspectPort === 'bignumberfunc') {
|
||||
clusterSettings.inspectPort = common.mustCall(
|
||||
() => 123121,
|
||||
workers.length
|
||||
);
|
||||
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
} else if (clusterSettings.inspectPort === 'strfunc') {
|
||||
clusterSettings.inspectPort = common.mustCall(
|
||||
() => 'invalidPort',
|
||||
workers.length
|
||||
);
|
||||
|
||||
cluster.setupMaster(clusterSettings);
|
||||
|
||||
assert.throws(() => {
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}, TypeError);
|
||||
|
||||
return;
|
||||
}
|
||||
cluster.setupMaster(clusterSettings);
|
||||
}
|
||||
|
||||
cluster.fork(params).on('exit', common.mustCall(checkExitCode));
|
||||
}
|
||||
}
|
||||
|
||||
function workerProcessMain() {
|
||||
const {expectedPort, expectedHost} = process.env;
|
||||
const {expectedPort, expectedInitialPort, expectedHost} = process.env;
|
||||
const debugOptions = process.binding('config').debugOptions;
|
||||
|
||||
assert.strictEqual(process.debugPort, +expectedPort);
|
||||
if ('expectedPort' in process.env) {
|
||||
assert.strictEqual(process.debugPort, +expectedPort);
|
||||
}
|
||||
|
||||
if (expectedHost !== 'undefined') {
|
||||
assert.strictEqual(
|
||||
process.binding('config').debugOptions.host,
|
||||
expectedHost
|
||||
);
|
||||
if ('expectedInitialPort' in process.env) {
|
||||
assert.strictEqual(debugOptions.port, +expectedInitialPort);
|
||||
}
|
||||
|
||||
if ('expectedHost' in process.env) {
|
||||
assert.strictEqual(debugOptions.host, expectedHost);
|
||||
}
|
||||
|
||||
process.exit();
|
||||
}
|
||||
|
||||
function spawnMaster({execArgv, workers}) {
|
||||
childProcess.fork(__filename, {
|
||||
env: {
|
||||
workers: JSON.stringify(workers),
|
||||
testProcess: true
|
||||
},
|
||||
execArgv
|
||||
}).on('exit', common.mustCall(checkExitCode));
|
||||
function spawnMaster({execArgv, workers, clusterSettings = {}}) {
|
||||
return new Promise((resolve) => {
|
||||
childProcess.fork(__filename, {
|
||||
env: {
|
||||
workers: JSON.stringify(workers),
|
||||
clusterSettings: JSON.stringify(clusterSettings),
|
||||
testProcess: true
|
||||
},
|
||||
execArgv
|
||||
}).on('exit', common.mustCall((code, signal) => {
|
||||
checkExitCode(code, signal);
|
||||
resolve();
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
function checkExitCode(code, signal) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user