Skip to content

Support auto attach for node.js subprocesses (aka cluster support) #40123

@weinand

Description

@weinand

While working on the Process viewer, I noticed that we could easily support node.js "Clusters" (or any other spawned processes) with a similar approach.

Here is a sketch:

  • introduce a new launch config attribute "autoAttachChildren"
  • if a launch config has "autoAttachChildren" set to true, node-debug starts to track creation of subprocesses of the debuggee.
  • if a subprocess is recognised as being in debug mode (e.g. started with one of more of the flags --inspect, --inspect-brk, --inspect-port, --debug, --debug-brk, --debug-port), node-debug starts an "attach" debug session for the given port.

The result looks like this (and a first cut will be available in the next Insiders).

2017-12-12_17-16-00

I've verified the feature (for macOS only) with the example from the node.js documentation for 'cluster':

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
	console.log(`Master ${process.pid} is running`);

	// Fork workers.
	for (let i = 0; i < numCPUs; i++) {
		cluster.fork();
	}

	cluster.on('exit', (worker, code, signal) => {
		console.log(`worker ${worker.process.pid} died`);
	});
} else {
	// Workers can share any TCP connection
	// In this case it is an HTTP server
	http.createServer((req, res) => {
		res.writeHead(200);
		res.end('hello world\n');
	}).listen(8000);

	console.log(`Worker ${process.pid} started`);
}

Here is the launch config:

{
	"type": "node",
	"request": "launch",
	"name": "Cluster",
	"program": "${workspaceFolder}/test.js",
	"autoAttachChildren": true
},

This already works fine for node.js < v8 (legacy).
For node.js >= v8 the problem is that all workers stop on entry, which requires some manual "continuing". The problem is that node-debug2 does not automatically send a "continue" request because it guesses that a "stop on entry" is desired. Node-debug1 had the same problem but I made it "guess" better in this case...

The work around for node.js >= v8 uses an explicit "--inspect" instead of "--inspect-brk":

{
	"type": "node",
	"request": "launch",
	"name": "Cluster (--inspect)",
	"runtimeArgs": [
		"--inspect=50000"
	],
	"port": 50000,
	"program": "${workspaceFolder}/test.js",
	"autoAttachChildren": true
},

The fix for node-debug was to only set this._stopOnEntry if it hasn't been set in the launch config:
see https://github.com/Microsoft/vscode-node-debug/blob/9a9ccb1703741fbad10e29d1769c0b8fc5cd3228/src/node/nodeDebug.ts#L1517

/cc @roblourens @auchenberg @isidorn

Metadata

Metadata

Assignees

Labels

debugDebug viewlet, configurations, breakpoints, adapter issuesfeature-requestRequest for new features or functionalityon-testplan

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions