diff --git a/lib/internal/cluster/master.js b/lib/internal/cluster/master.js index 2d1e2d3097f75b..85e0f98d6bf95a 100644 --- a/lib/internal/cluster/master.js +++ b/lib/internal/cluster/master.js @@ -26,6 +26,7 @@ cluster.SCHED_RR = SCHED_RR; // Master distributes connections. var ids = 0; var debugPortOffset = 1; var initialized = false; +let debugSettingsOverriden = false; // XXX(bnoordhuis) Fold cluster.schedulingPolicy into cluster.settings? var schedulingPolicy = { @@ -41,7 +42,7 @@ if (schedulingPolicy === undefined) { cluster.schedulingPolicy = schedulingPolicy; -cluster.setupMaster = function(options) { +cluster.setupMaster = function(options = {}) { var settings = { args: process.argv.slice(2), exec: process.argv[1], @@ -49,7 +50,7 @@ cluster.setupMaster = function(options) { silent: false }; util._extend(settings, cluster.settings); - util._extend(settings, options || {}); + util._extend(settings, options); // Tell V8 to write profile data for each process to a separate file. // Without --logfile=v8-%p.log, everything ends up in a single, unusable @@ -60,6 +61,14 @@ cluster.setupMaster = function(options) { settings.execArgv = settings.execArgv.concat(['--logfile=v8-%p.log']); } + // This allows user to override inspect port for workers. + const debugPortArgsRegex = /--inspect(=|-port=)|--debug-port=/; + + if (!debugSettingsOverriden && options.execArgv && + options.execArgv.some((arg) => arg.match(debugPortArgsRegex))) { + debugSettingsOverriden = true; + } + cluster.settings = settings; if (initialized === true) @@ -103,7 +112,8 @@ function createWorkerProcess(id, env) { util._extend(workerEnv, env); workerEnv.NODE_UNIQUE_ID = '' + id; - if (execArgv.some((arg) => arg.match(debugArgRegex))) { + if (!debugSettingsOverriden && + execArgv.some((arg) => arg.match(debugArgRegex))) { execArgv.push(`--inspect-port=${process.debugPort + debugPortOffset}`); debugPortOffset++; } diff --git a/test/inspector/test-inspector-port-cluster.js b/test/inspector/test-inspector-port-cluster.js index b2a53f87ea172e..6ddd97437f1ae8 100644 --- a/test/inspector/test-inspector-port-cluster.js +++ b/test/inspector/test-inspector-port-cluster.js @@ -23,7 +23,7 @@ function testRunnerMain() { workers: [{expectedPort: 9230}] }); - let port = debuggerPort + offset++ * 10; + let port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: [`--inspect=${port}`], @@ -34,28 +34,28 @@ function testRunnerMain() { ] }); - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: ['--inspect', `--inspect-port=${port}`], workers: [{expectedPort: port + 1}] }); - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: ['--inspect', `--debug-port=${port}`], workers: [{expectedPort: port + 1}] }); - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: [`--inspect=0.0.0.0:${port}`], workers: [{expectedPort: port + 1, expectedHost: '0.0.0.0'}] }); - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: [`--inspect=127.0.0.1:${port}`], @@ -63,52 +63,143 @@ function testRunnerMain() { }); if (common.hasIPv6) { - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: [`--inspect=[::]:${port}`], workers: [{expectedPort: port + 1, expectedHost: '::'}] }); - port = debuggerPort + offset++ * 10; + port = debuggerPort + offset++ * 5; spawnMaster({ execArgv: [`--inspect=[::1]:${port}`], workers: [{expectedPort: port + 1, expectedHost: '::1'}] }); } + + /* + * Following tests check that port should not increment + * if developer sets inspector port in cluster.setupMaster arguments. + */ + + port = debuggerPort + offset++ * 5; + + spawnMaster({ + execArgv: [`--inspect=${port}`], + workers: [ + {expectedPort: port + 2}, + {expectedPort: port + 4}, + {expectedPort: port + 6} + ], + clusterExecArgv: [ + [`--inspect=${port + 2}`], + [`--inspect-port=${port + 4}`], + [`--debug-port=${port + 6}`], + ] + }); + + port = debuggerPort + offset++ * 5; + + spawnMaster({ + execArgv: [], + workers: [ + {expectedPort: port} + ], + clusterExecArgv: [ + [`--inspect=${port}`] + ] + }); + + // Next tests check that inspector port incrementing logic + // is disabled if zero port passed to workers. + // Even if supplied execArgv is equal to master's. + + spawnMaster({ + execArgv: [], + workers: [ + {expectedInitialPort: 0}, + {expectedInitialPort: 0}, + {expectedInitialPort: 0} + ], + clusterExecArgv: [ + ['--inspect=0'], + ['--inspect=0'], + ['--inspect=0'] + ] + }); + + spawnMaster({ + execArgv: ['--inspect=0'], + workers: [ + {expectedInitialPort: 0}, + {expectedInitialPort: 0}, + {expectedInitialPort: 0} + ], + clusterExecArgv: [ + ['--inspect=0'], + ['--inspect=0'], + ['--inspect=0'] + ] + }); + + spawnMaster({ + execArgv: ['--inspect=0'], + workers: [ + {expectedInitialPort: 0}, + {expectedInitialPort: 0}, + {expectedInitialPort: 0} + ], + clusterExecArgv: [ + ['--inspect', '--inspect-port=0'], + ['--inspect', '--inspect-port=0'], + ['--inspect', '--inspect-port=0'] + ] + }); + } function masterProcessMain() { const workers = JSON.parse(process.env.workers); + const clusterExecArgv = JSON.parse(process.env.clusterExecArgv); + + for (const [index, worker] of workers.entries()) { + if (clusterExecArgv[index]) { + cluster.setupMaster({execArgv: clusterExecArgv[index]}); + } - for (const worker of workers) { cluster.fork({ expectedPort: worker.expectedPort, + expectedInitialPort: worker.expectedInitialPort, expectedHost: worker.expectedHost }).on('exit', common.mustCall(checkExitCode)); } } function workerProcessMain() { - const {expectedPort, expectedHost} = process.env; + const {expectedPort, expectedInitialPort, expectedHost} = process.env; + const debugOptions = process.binding('config').debugOptions; + + if (+expectedPort) { + assert.strictEqual(process.debugPort, +expectedPort); + } - assert.strictEqual(process.debugPort, +expectedPort); + if (+expectedInitialPort) { + assert.strictEqual(debugOptions.port, +expectedInitialPort); + } if (expectedHost !== 'undefined') { - assert.strictEqual( - process.binding('config').debugOptions.host, - expectedHost - ); + assert.strictEqual(debugOptions.host, expectedHost); } process.exit(); } -function spawnMaster({execArgv, workers}) { +function spawnMaster({execArgv, workers, clusterExecArgv = []}) { childProcess.fork(__filename, { env: { workers: JSON.stringify(workers), + clusterExecArgv: JSON.stringify(clusterExecArgv), testProcess: true }, execArgv