Browse Source

debugger: don't spawn child process in remote mode

When debug in remote mode with host:port or pid, the interface
spawn child process also. If the debugger agent is running, will
get following output:

```
< Error: listen EADDRINUSE :::5858
<     at Object.exports._errnoException (util.js:734:11)
<     at exports._exceptionWithHostPort (util.js:757:20)
<     at Agent.Server._listen2 (net.js:1155:14)
<     at listen (net.js:1181:10)
<     at Agent.Server.listen (net.js:1268:5)
<     at Object.start (_debug_agent.js:21:9)
<     at startup (node.js:68:9)
<     at node.js:799:3
```

This fix won't spawn child process and no more error message was
shown.

When use `iojs debug`, the tip information just like this:

```
Usage: iojs debug script.js
```

This fix will display the advance usage also:

```
Usage: iojs debug script.js
       iojs debug <host>:<port>
       iojs debug -p <pid>
```

Fixes: https://github.com/iojs/io.js/issues/889
PR-URL: https://github.com/iojs/io.js/pull/1282
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
v1.8.0-commit
Jackson Tian 10 years ago
committed by Ben Noordhuis
parent
commit
a2ea16838f
  1. 41
      lib/_debugger.js
  2. 52
      test/debugger/test-debugger-remote.js

41
lib/_debugger.js

@ -15,6 +15,8 @@ exports.start = function(argv, stdin, stdout) {
if (argv.length < 1) { if (argv.length < 1) {
console.error('Usage: iojs debug script.js'); console.error('Usage: iojs debug script.js');
console.error(' iojs debug <host>:<port>');
console.error(' iojs debug -p <pid>');
process.exit(1); process.exit(1);
} }
@ -1626,6 +1628,7 @@ Interface.prototype.trySpawn = function(cb) {
this.killChild(); this.killChild();
assert(!this.child); assert(!this.child);
var isRemote = false;
if (this.args.length === 2) { if (this.args.length === 2) {
var match = this.args[1].match(/^([^:]+):(\d+)$/); var match = this.args[1].match(/^([^:]+):(\d+)$/);
@ -1634,21 +1637,13 @@ Interface.prototype.trySpawn = function(cb) {
// `node debug localhost:5858` // `node debug localhost:5858`
host = match[1]; host = match[1];
port = parseInt(match[2], 10); port = parseInt(match[2], 10);
this.child = { isRemote = true;
kill: function() {
// TODO Do we really need to handle it?
}
};
} }
} else if (this.args.length === 3) { } else if (this.args.length === 3) {
// `node debug -p pid` // `node debug -p pid`
if (this.args[1] === '-p' && /^\d+$/.test(this.args[2])) { if (this.args[1] === '-p' && /^\d+$/.test(this.args[2])) {
this.child = {
kill: function() {
// TODO Do we really need to handle it?
}
};
process._debugProcess(parseInt(this.args[2], 10)); process._debugProcess(parseInt(this.args[2], 10));
isRemote = true;
} else { } else {
var match = this.args[1].match(/^--port=(\d+)$/); var match = this.args[1].match(/^--port=(\d+)$/);
if (match) { if (match) {
@ -1660,10 +1655,13 @@ Interface.prototype.trySpawn = function(cb) {
} }
} }
this.child = spawn(process.execPath, childArgs); if (!isRemote) {
// pipe stream into debugger
this.child = spawn(process.execPath, childArgs);
this.child.stdout.on('data', this.childPrint.bind(this)); this.child.stdout.on('data', this.childPrint.bind(this));
this.child.stderr.on('data', this.childPrint.bind(this)); this.child.stderr.on('data', this.childPrint.bind(this));
}
this.pause(); this.pause();
@ -1707,9 +1705,10 @@ Interface.prototype.trySpawn = function(cb) {
client.on('error', connectError); client.on('error', connectError);
function connectError() { function connectError() {
// If it's failed to connect 4 times then don't catch the next error // If it's failed to connect 10 times then print failed message
if (connectionAttempts >= 10) { if (connectionAttempts >= 10) {
client.removeListener('error', connectError); self.stdout.write(' failed, please retry\n');
return;
} }
setTimeout(attemptConnect, 500); setTimeout(attemptConnect, 500);
} }
@ -1720,10 +1719,12 @@ Interface.prototype.trySpawn = function(cb) {
client.connect(port, host); client.connect(port, host);
} }
this.child.stderr.once('data', function() { self.print('connecting to ' + host + ':' + port + ' ..', true);
setImmediate(function() { if (isRemote) {
self.print('connecting to port ' + port + '..', true); attemptConnect();
attemptConnect(); } else {
this.child.stderr.once('data', function() {
setImmediate(attemptConnect);
}); });
}); }
}; };

52
test/debugger/test-debugger-remote.js

@ -0,0 +1,52 @@
var common = require('../common');
var assert = require('assert');
var spawn = require('child_process').spawn;
var port = common.PORT + 1337;
var buffer = '';
var expected = [];
var scriptToDebug = common.fixturesDir + '/empty.js';
function fail() {
assert(0); // `iojs --debug-brk script.js` should not quit
}
// running with debug agent
var child = spawn(process.execPath, ['--debug-brk=5959', scriptToDebug]);
console.error(process.execPath, '--debug-brk=5959', scriptToDebug);
// connect to debug agent
var interfacer = spawn(process.execPath, ['debug', 'localhost:5959']);
console.error(process.execPath, 'debug', 'localhost:5959');
interfacer.stdout.setEncoding('utf-8');
interfacer.stdout.on('data', function(data) {
data = (buffer + data).split('\n');
buffer = data.pop();
data.forEach(function(line) {
interfacer.emit('line', line);
});
});
interfacer.on('line', function(line) {
line = line.replace(/^(debug> *)+/, '');
console.log(line);
var expected = '\bconnecting to localhost:5959 ... ok';
assert.ok(expected == line, 'Got unexpected line: ' + line);
});
// give iojs time to start up the debugger
setTimeout(function() {
child.removeListener('exit', fail);
child.kill();
interfacer.removeListener('exit', fail);
interfacer.kill();
}, 2000);
process.on('exit', function() {
assert(child.killed);
assert(interfacer.killed);
});
interfacer.stderr.pipe(process.stderr);
Loading…
Cancel
Save