40

I'm trying to debug the child Node.JS process created using:

var child = require('child_process');
child .fork(__dirname + '/task.js');

The problem is that when running in IntelliJ/WebStorm both parent and child process start on the same port.

debugger listening on port 40893
debugger listening on port 40893

So it only debugs the parent process.

Is there any way to set IntelliJ to debug the child process or force it to start on a different port so I can connect it in Remote debug?

Guy Korland
  • 9,139
  • 14
  • 59
  • 106

6 Answers6

30

Yes. You have to spawn your process in a new port. There is a workaround to debug with clusters, in the same way you can do:

Start your app with the --debug command and then:

var child = require('child_process');
var debug = typeof v8debug === 'object';
if (debug) {   
    //Set an unused port number.    
    process.execArgv.push('--debug=' + (40894));    
}    
child.fork(__dirname + '/task.js');

debugger listening on port 40894

Oleg Belousov
  • 9,981
  • 14
  • 72
  • 127
davidforneron
  • 739
  • 9
  • 12
  • I'm not sure why, but my process.execArgv is an array, I had to modify it to process.execArgv.toString().indexOf('--debug') !== -1; in order to get it to work. Thanks! – MorningDew Nov 20 '14 at 02:27
  • Using node 0.12.1, problem still exists, the condition did not return true(checking for debug), but changing the port the way that you suggested worked. – Oleg Belousov Jul 21 '15 at 10:19
22

It is a known bug in node.js that has been recently fixed (although not backported to v0.10).

See this issue for more details: https://github.com/joyent/node/issues/5318

There is a workaround where you alter the command-line for each worker process, although the API was not meant to be used this way (the workaround might stop working in the future). Here is the source code from the github issue:

var cluster = require('cluster');
var http = require('http');

if (cluster.isMaster) {
  var debug = process.execArgv.indexOf('--debug') !== -1;
  cluster.setupMaster({
    execArgv: process.execArgv.filter(function(s) { return s !== '--debug' })
  });
  for (var i = 0; i < 2; ++i) {
    if (debug) cluster.settings.execArgv.push('--debug=' + (5859 + i));
    cluster.fork();
    if (debug) cluster.settings.execArgv.pop();
  }
}
else {
  var server = http.createServer(function(req, res) {
    res.end('OK');
  });
  server.listen(8000);
}
Miroslav Bajtoš
  • 10,667
  • 1
  • 41
  • 99
  • 1
    Is there a way to achieve the same thing with child.fork()? – Guy Korland May 30 '13 at 19:44
  • 3
    @GuyKorland Of course, just add --debug={port} to command-line arguments of your child process. – Miroslav Bajtoš May 31 '13 at 06:25
  • see also [this comment](http://youtrack.jetbrains.com/issue/WEB-1919#comment=27-401139) – lena May 31 '13 at 14:54
  • I struggled on this because I affected the child_process module to a local variable called process, hiding the node process global variable, hence process.execArgv was not defined. Beaware "process" is a node global variable! – Rémy DAVID Sep 30 '14 at 09:54
15

Quick simple fix ( where using chrome://inspect/#devices )

var child = require('child_process');
child.fork(__dirname + '/task.js',[],{execArgv:['--inspect-brk']});

Then run your app without any --inspect-brk and the main process won't debug but the forked process will and no conflicts.

To stop a fork conflicting when debugging the main process ;

child.fork(__dirname + '/task.js',[],{execArgv:['--inspect=xxxx']});

where xxxx is some port not being used for debugging the main process. Though I haven't managed to easily connect to both at the same time in the debugger even though it reports as listening.

Bob
  • 1,589
  • 17
  • 25
  • This worked great for me when nothing else did kudos. – qbert65536 Jan 10 '19 at 21:00
  • 1
    For other's trying to use spawn but not having it work, I find that this works for me: `child.spawn('node',['--inspect-brk', __dirname + '/task.js']);` – tnrich Oct 24 '19 at 06:30
4

I find that setting the 'execArgv' attribute in the fork func will work:

const child = fork('start.js', [], {
cwd: startPath,
silent: true,
execArgv: ['--inspect=10245'] });
Jar Lin
  • 41
  • 1
3

if "process.execArgv" doenst work you have to try:

if (debug) {
    process.argv.push('--debug=' + (40894));
}

this worked for me..

1

There are one more modern way to debug child (or any) process with Chrome DevTools.

Start your app with arg

--inspect

like below:

node --debug=9200 --inspect app/main.js

You will see the message with URL for each child process:

Debugger listening on port 9200.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9200/207f2ab6-5700-4fc5-b6d3-c49a4b34a311
Debugger listening on port 9201.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9201/97be3351-2ea1-4541-b744-e720188bacfa
Debugger listening on port 9202.
Warning: This is an experimental feature and could change at any time.
To start debugging, open the following URL in Chrome:
    chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:9202/8eb8384a-7167-40e9-911a-5a8b902bb8c9

If you want to debug the remote processes, just change the address 127.0.0.1 to your own.

VooVoo
  • 21
  • 1
  • 5
  • 1
    --inspect is the modern way, but it doesn't has much to do with the problem here - debugging a child process. – Liang Zhou Feb 04 '17 at 17:50
  • 1
    Chrome will not discover the extra ports automatically. You have to tell it to connect with them manually. – Breedly Jan 11 '18 at 22:28