Skip to content

Commit dfc46e2

Browse files
mutantcornholioaddaleax
authored andcommitted
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: #14140Fixes: #8495Fixes: #12941 Refs: #9659 Refs: #13761 Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent d651a01 commit dfc46e2

File tree

3 files changed

+251
-23
lines changed

3 files changed

+251
-23
lines changed

‎doc/api/cluster.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -746,6 +746,9 @@ changes:
746746
`'ipc'` entry. When this option is provided, it overrides `silent`.
747747
*`uid`{number} Sets the user identity of the process. (See setuid(2).)
748748
*`gid`{number} Sets the group identity of the process. (See setgid(2).)
749+
*`inspectPort`{number|function} Sets inspector port of worker.
750+
Accepts number, or function that evaluates to number. By default
751+
each worker gets port, incremented from master's `process.debugPort`.
749752

750753
After calling `.setupMaster()` (or `.fork()`) this settings object will contain
751754
the settings, including the default values.

‎lib/internal/cluster/master.js‎

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const cluster = new EventEmitter();
1212
constintercom=newEventEmitter();
1313
constSCHED_NONE=1;
1414
constSCHED_RR=2;
15+
const{isLegalPort}=require('internal/net');
1516

1617
module.exports=cluster;
1718

@@ -104,8 +105,23 @@ function createWorkerProcess(id, env){
104105
workerEnv.NODE_UNIQUE_ID=''+id;
105106

106107
if(execArgv.some((arg)=>arg.match(debugArgRegex))){
107-
execArgv.push(`--inspect-port=${process.debugPort+debugPortOffset}`);
108-
debugPortOffset++;
108+
letinspectPort;
109+
if('inspectPort'incluster.settings){
110+
if(typeofcluster.settings.inspectPort==='function')
111+
inspectPort=cluster.settings.inspectPort();
112+
else
113+
inspectPort=cluster.settings.inspectPort;
114+
115+
if(!isLegalPort(inspectPort)){
116+
thrownewTypeError('cluster.settings.inspectPort'+
117+
' is invalid');
118+
}
119+
}else{
120+
inspectPort=process.debugPort+debugPortOffset;
121+
debugPortOffset++;
122+
}
123+
124+
execArgv.push(`--inspect-port=${inspectPort}`);
109125
}
110126

111127
returnfork(cluster.settings.exec,cluster.settings.args,{

‎test/inspector/test-inspector-port-cluster.js‎

Lines changed: 230 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ let offset = 0;
1818
*/
1919

2020
functiontestRunnerMain(){
21-
spawnMaster({
21+
letdefaultPortCase=spawnMaster({
2222
execArgv: ['--inspect'],
2323
workers: [{expectedPort: 9230}]
2424
});
@@ -77,42 +77,251 @@ function testRunnerMain(){
7777
workers: [{expectedPort: port+1,expectedHost: '::1'}]
7878
});
7979
}
80-
}
8180

81+
// These tests check that setting inspectPort in cluster.settings
82+
// would take effect and override port incrementing behavior
83+
84+
port=debuggerPort+offset++*5;
85+
86+
spawnMaster({
87+
execArgv: [`--inspect=${port}`],
88+
clusterSettings: {inspectPort: port+2},
89+
workers: [{expectedPort: port+2}]
90+
});
91+
92+
port=debuggerPort+offset++*5;
93+
94+
spawnMaster({
95+
execArgv: [`--inspect=${port}`],
96+
clusterSettings: {inspectPort: 'addTwo'},
97+
workers: [
98+
{expectedPort: port+2},
99+
{expectedPort: port+4}
100+
]
101+
});
102+
103+
port=debuggerPort+offset++*5;
104+
105+
spawnMaster({
106+
execArgv: [`--inspect=${port}`],
107+
clusterSettings: {inspectPort: 'string'},
108+
workers: [{}]
109+
});
110+
111+
port=debuggerPort+offset++*5;
112+
113+
spawnMaster({
114+
execArgv: [`--inspect=${port}`],
115+
clusterSettings: {inspectPort: 'null'},
116+
workers: [{}]
117+
});
118+
119+
port=debuggerPort+offset++*5;
120+
121+
spawnMaster({
122+
execArgv: [`--inspect=${port}`],
123+
clusterSettings: {inspectPort: 'bignumber'},
124+
workers: [{}]
125+
});
126+
127+
port=debuggerPort+offset++*5;
128+
129+
spawnMaster({
130+
execArgv: [`--inspect=${port}`],
131+
clusterSettings: {inspectPort: 'negativenumber'},
132+
workers: [{}]
133+
});
134+
135+
port=debuggerPort+offset++*5;
136+
137+
spawnMaster({
138+
execArgv: [`--inspect=${port}`],
139+
clusterSettings: {inspectPort: 'bignumberfunc'},
140+
workers: [{}]
141+
});
142+
143+
port=debuggerPort+offset++*5;
144+
145+
spawnMaster({
146+
execArgv: [`--inspect=${port}`],
147+
clusterSettings: {inspectPort: 'strfunc'},
148+
workers: [{}]
149+
});
150+
151+
port=debuggerPort+offset++*5;
152+
153+
spawnMaster({
154+
execArgv: [],
155+
clusterSettings: {inspectPort: port,execArgv: ['--inspect']},
156+
workers: [
157+
{expectedPort: port}
158+
]
159+
});
160+
161+
port=debuggerPort+offset++*5;
162+
163+
spawnMaster({
164+
execArgv: [`--inspect=${port}`],
165+
clusterSettings: {inspectPort: 0},
166+
workers: [
167+
{expectedInitialPort: 0},
168+
{expectedInitialPort: 0},
169+
{expectedInitialPort: 0}
170+
]
171+
});
172+
173+
port=debuggerPort+offset++*5;
174+
175+
spawnMaster({
176+
execArgv: [],
177+
clusterSettings: {inspectPort: 0},
178+
workers: [
179+
{expectedInitialPort: 0},
180+
{expectedInitialPort: 0},
181+
{expectedInitialPort: 0}
182+
]
183+
});
184+
185+
defaultPortCase.then(()=>{
186+
port=debuggerPort+offset++*5;
187+
defaultPortCase=spawnMaster({
188+
execArgv: ['--inspect'],
189+
clusterSettings: {inspectPort: port+2},
190+
workers: [
191+
{expectedInitialPort: port+2}
192+
]
193+
});
194+
});
195+
}
82196
functionmasterProcessMain(){
83197
constworkers=JSON.parse(process.env.workers);
198+
constclusterSettings=JSON.parse(process.env.clusterSettings);
199+
letdebugPort=process.debugPort;
84200

85201
for(constworkerofworkers){
86-
cluster.fork({
87-
expectedPort: worker.expectedPort,
88-
expectedHost: worker.expectedHost
89-
}).on('exit',common.mustCall(checkExitCode));
202+
constparams={};
203+
204+
if(worker.expectedPort){
205+
params.expectedPort=worker.expectedPort;
206+
}
207+
208+
if(worker.expectedInitialPort){
209+
params.expectedInitialPort=worker.expectedInitialPort;
210+
}
211+
212+
if(worker.expectedHost){
213+
params.expectedHost=worker.expectedHost;
214+
}
215+
216+
if(clusterSettings){
217+
if(clusterSettings.inspectPort==='addTwo'){
218+
clusterSettings.inspectPort=common.mustCall(
219+
()=>{returndebugPort+=2;},
220+
workers.length
221+
);
222+
}elseif(clusterSettings.inspectPort==='string'){
223+
clusterSettings.inspectPort='string';
224+
cluster.setupMaster(clusterSettings);
225+
226+
assert.throws(()=>{
227+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
228+
},TypeError);
229+
230+
return;
231+
}elseif(clusterSettings.inspectPort==='null'){
232+
clusterSettings.inspectPort=null;
233+
cluster.setupMaster(clusterSettings);
234+
235+
assert.throws(()=>{
236+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
237+
},TypeError);
238+
239+
return;
240+
}elseif(clusterSettings.inspectPort==='bignumber'){
241+
clusterSettings.inspectPort=1293812;
242+
cluster.setupMaster(clusterSettings);
243+
244+
assert.throws(()=>{
245+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
246+
},TypeError);
247+
248+
return;
249+
}elseif(clusterSettings.inspectPort==='negativenumber'){
250+
clusterSettings.inspectPort=-9776;
251+
cluster.setupMaster(clusterSettings);
252+
253+
assert.throws(()=>{
254+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
255+
},TypeError);
256+
257+
return;
258+
}elseif(clusterSettings.inspectPort==='bignumberfunc'){
259+
clusterSettings.inspectPort=common.mustCall(
260+
()=>123121,
261+
workers.length
262+
);
263+
264+
cluster.setupMaster(clusterSettings);
265+
266+
assert.throws(()=>{
267+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
268+
},TypeError);
269+
270+
return;
271+
}elseif(clusterSettings.inspectPort==='strfunc'){
272+
clusterSettings.inspectPort=common.mustCall(
273+
()=>'invalidPort',
274+
workers.length
275+
);
276+
277+
cluster.setupMaster(clusterSettings);
278+
279+
assert.throws(()=>{
280+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
281+
},TypeError);
282+
283+
return;
284+
}
285+
cluster.setupMaster(clusterSettings);
286+
}
287+
288+
cluster.fork(params).on('exit',common.mustCall(checkExitCode));
90289
}
91290
}
92291

93292
functionworkerProcessMain(){
94-
const{expectedPort, expectedHost}=process.env;
293+
const{expectedPort, expectedInitialPort, expectedHost}=process.env;
294+
constdebugOptions=process.binding('config').debugOptions;
295+
296+
if('expectedPort'inprocess.env){
297+
assert.strictEqual(process.debugPort,+expectedPort);
298+
}
95299

96-
assert.strictEqual(process.debugPort,+expectedPort);
300+
if('expectedInitialPort'inprocess.env){
301+
assert.strictEqual(debugOptions.port,+expectedInitialPort);
302+
}
97303

98-
if(expectedHost!=='undefined'){
99-
assert.strictEqual(
100-
process.binding('config').debugOptions.host,
101-
expectedHost
102-
);
304+
if('expectedHost'inprocess.env){
305+
assert.strictEqual(debugOptions.host,expectedHost);
103306
}
104307

105308
process.exit();
106309
}
107310

108-
functionspawnMaster({execArgv, workers}){
109-
childProcess.fork(__filename,{
110-
env: {
111-
workers: JSON.stringify(workers),
112-
testProcess: true
113-
},
114-
execArgv
115-
}).on('exit',common.mustCall(checkExitCode));
311+
functionspawnMaster({execArgv, workers, clusterSettings ={}}){
312+
returnnewPromise((resolve)=>{
313+
childProcess.fork(__filename,{
314+
env: {
315+
workers: JSON.stringify(workers),
316+
clusterSettings: JSON.stringify(clusterSettings),
317+
testProcess: true
318+
},
319+
execArgv
320+
}).on('exit',common.mustCall((code,signal)=>{
321+
checkExitCode(code,signal);
322+
resolve();
323+
}));
324+
});
116325
}
117326

118327
functioncheckExitCode(code,signal){

0 commit comments

Comments
(0)