Browse Source

src: remove support for --debug

In the 2017-04-05 meeting, the CTC agreed to remove support for the
legacy debugger in 8.0.0. This is the first step in this direction.

Refs: https://github.com/nodejs/CTC/issues/94
PR-URL: https://github.com/nodejs/node/pull/12197
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
v6
Jan Krems 8 years ago
committed by Michaël Zasso
parent
commit
47f8f7462f
  1. 19
      doc/api/debugger.md
  2. 5
      doc/api/process.md
  3. 10
      src/node_debug_options.cc
  4. 0
      test/known_issues/test-cluster-disconnect-handles.js
  5. 42
      test/parallel/test-cluster-debug-port.js
  6. 8
      test/parallel/test-cluster-inspector-debug-port.js
  7. 13
      test/parallel/test-debug-brk-no-arg.js
  8. 70
      test/parallel/test-debug-brk.js
  9. 26
      test/parallel/test-debug-no-context.js
  10. 52
      test/parallel/test-debug-port-cluster.js
  11. 63
      test/parallel/test-debug-port-from-cmdline.js
  12. 59
      test/parallel/test-debug-port-numbers.js
  13. 113
      test/parallel/test-debug-signal-cluster.js
  14. 59
      test/parallel/test-debugger-util-regression.js
  15. 45
      test/sequential/test-debug-host-port.js
  16. 31
      test/sequential/test-debugger-debug-brk.js

19
doc/api/debugger.md

@ -169,27 +169,8 @@ breakpoint)
## Advanced Usage
### TCP-based protocol
> Stability: 0 - Deprecated: Use [V8 Inspector Integration][] instead.
The debug protocol used by the `--debug` flag was removed from V8.
An alternative way of enabling and accessing the debugger is to start
Node.js with the `--debug` command-line flag or by signaling an existing
Node.js process with `SIGUSR1`.
Once a process has been set in debug mode this way, it can be inspected
using the Node.js debugger by either connecting to the `pid` of the running
process or via URI reference to the listening debugger:
* `node debug -p <pid>` - Connects to the process via the `pid`
* `node debug <URI>` - Connects to the process via the URI such as
localhost:5858
### V8 Inspector Integration for Node.js
**NOTE: This is an experimental feature.**
V8 Inspector integration allows attaching Chrome DevTools to Node.js
instances for debugging and profiling. It uses the [Chrome Debugging Protocol][].

5
doc/api/process.md

@ -1757,9 +1757,8 @@ cases:
source code internal in Node.js's bootstrapping process threw an error
when the bootstrapping function was called. This is extremely rare,
and generally can only happen during development of Node.js itself.
* `12` **Invalid Debug Argument** - The `--debug`, `--inspect` and/or
`--debug-brk` options were set, but the port number chosen was invalid
or unavailable.
* `12` **Invalid Debug Argument** - The `--inspect` and/or `--inspect-brk`
options were set, but the port number chosen was invalid or unavailable.
* `>128` **Signal Exits** - If Node.js receives a fatal signal such as
`SIGKILL` or `SIGHUP`, then its exit code will be `128` plus the
value of the signal code. This is a standard Unix practice, since

10
src/node_debug_options.cc

@ -92,13 +92,7 @@ bool DebugOptions::ParseOption(const std::string& option) {
argument = option.substr(pos + 1);
}
// --debug and --inspect are mutually exclusive
if (option_name == "--debug") {
debugger_enabled_ = true;
} else if (option_name == "--debug-brk") {
debugger_enabled_ = true;
wait_connect_ = true;
} else if (option_name == "--inspect") {
if (option_name == "--inspect") {
debugger_enabled_ = true;
enable_inspector = true;
} else if (option_name == "--inspect-brk") {
@ -108,7 +102,7 @@ bool DebugOptions::ParseOption(const std::string& option) {
} else if ((option_name != "--debug-port" &&
option_name != "--inspect-port") ||
!has_argument) {
// only other valid possibility is --debug-port,
// only other valid possibility is --inspect-port,
// which requires an argument
return false;
}

0
test/parallel/test-cluster-disconnect-handles.js → test/known_issues/test-cluster-disconnect-handles.js

42
test/parallel/test-cluster-debug-port.js

@ -1,42 +0,0 @@
'use strict';
require('../common');
const assert = require('assert');
const cluster = require('cluster');
if (cluster.isMaster) {
function checkExitCode(code, signal) {
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
}
console.log('forked worker should not have --debug-port');
cluster.fork().on('exit', checkExitCode);
cluster.setupMaster({
execArgv: ['--debug-port=' + process.debugPort]
});
console.log('forked worker should have --debug-port, with offset = 1');
cluster.fork({
portSet: process.debugPort + 1
}).on('exit', checkExitCode);
cluster.setupMaster({
execArgv: [`--debug-port=${process.debugPort}`,
`--debug=${process.debugPort}`]
});
console.log('forked worker should have --debug-port, with offset = 2');
cluster.fork({
portSet: process.debugPort + 2
}).on('exit', checkExitCode);
} else {
const hasDebugArg = process.execArgv.some(function(arg) {
return /debug/.test(arg);
});
assert.strictEqual(hasDebugArg, process.env.portSet !== undefined);
assert.strictEqual(process.debugPort, +process.env.portSet || 5858);
process.exit();
}

8
test/parallel/test-cluster-inspector-debug-port.js

@ -25,11 +25,9 @@ if (cluster.isMaster) {
fork(1);
fork(2, ['--inspect']);
fork(3, [`--inspect=${debuggerPort}`]);
fork(4, ['--inspect', '--debug']);
fork(5, [`--debug=${debuggerPort}`, '--inspect']);
fork(6, ['--inspect', `--debug-port=${debuggerPort}`]);
fork(7, [`--inspect-port=${debuggerPort}`]);
fork(8, ['--inspect', `--inspect-port=${debuggerPort}`]);
fork(4, ['--inspect', `--debug-port=${debuggerPort}`]);
fork(5, [`--inspect-port=${debuggerPort}`]);
fork(6, ['--inspect', `--inspect-port=${debuggerPort}`]);
} else {
const hasDebugArg = process.execArgv.some(function(arg) {
return /inspect/.test(arg);

13
test/parallel/test-debug-brk-no-arg.js

@ -1,13 +0,0 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
const child = spawn(process.execPath, ['--debug-brk=' + common.PORT, '-i']);
child.stderr.once('data', common.mustCall(function() {
child.stdin.end('.exit');
}));
child.on('exit', common.mustCall(function(c) {
assert.strictEqual(c, 0);
}));

70
test/parallel/test-debug-brk.js

@ -1,70 +0,0 @@
'use strict';
const common = require('../common');
const spawn = require('child_process').spawn;
let run = common.noop;
function test(extraArgs, stdoutPattern) {
const next = run;
run = () => {
let procStdout = '';
let procStderr = '';
let agentStdout = '';
let debuggerListening = false;
let outputMatched = false;
let needToSpawnAgent = true;
let needToExit = true;
const procArgs = [`--debug-brk=${common.PORT}`].concat(extraArgs);
const proc = spawn(process.execPath, procArgs);
proc.stderr.setEncoding('utf8');
const tryStartAgent = () => {
if (debuggerListening && outputMatched && needToSpawnAgent) {
needToSpawnAgent = false;
const agentArgs = ['debug', `localhost:${common.PORT}`];
const agent = spawn(process.execPath, agentArgs);
agent.stdout.setEncoding('utf8');
agent.stdout.on('data', (chunk) => {
agentStdout += chunk;
if (/connecting to .+ ok/.test(agentStdout) && needToExit) {
needToExit = false;
exitAll([proc, agent]);
}
});
}
};
const exitAll = common.mustCall((processes) => {
processes.forEach((myProcess) => { myProcess.kill(); });
});
if (stdoutPattern != null) {
proc.stdout.on('data', (chunk) => {
procStdout += chunk;
outputMatched = outputMatched || stdoutPattern.test(procStdout);
tryStartAgent();
});
} else {
outputMatched = true;
}
proc.stderr.on('data', (chunk) => {
procStderr += chunk;
debuggerListening = debuggerListening ||
/Debugger listening on/.test(procStderr);
tryStartAgent();
});
proc.on('exit', () => {
next();
});
};
}
test(['-e', '0']);
test(['-e', '0', 'foo']);
test(['-p', 'process.argv[1]', 'foo'], /^\s*foo\s*$/);
run();

26
test/parallel/test-debug-no-context.js

@ -1,26 +0,0 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
const args = ['--debug', `--debug-port=${common.PORT}`, '--interactive'];
const proc = spawn(process.execPath, args);
proc.stdin.write(`
util.inspect(Promise.resolve(42));
util.inspect(Promise.resolve(1337));
.exit
`);
proc.on('exit', common.mustCall((exitCode, signalCode) => {
// This next line should be included but unfortunately Win10 fails from time
// to time in CI. See https://github.com/nodejs/node/issues/5268
// assert.strictEqual(exitCode, 0);
assert.strictEqual(signalCode, null);
}));
let stdout = '';
proc.stdout.setEncoding('utf8');
proc.stdout.on('data', (data) => stdout += data);
process.on('exit', () => {
assert(stdout.includes('Promise { 42 }'));
assert(stdout.includes('Promise { 1337 }'));
});

52
test/parallel/test-debug-port-cluster.js

@ -1,52 +0,0 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
const PORT_MIN = common.PORT + 1; // The fixture uses common.PORT.
const PORT_MAX = PORT_MIN + 2;
const args = [
'--debug=' + PORT_MIN,
common.fixturesDir + '/clustered-server/app.js'
];
const child = spawn(process.execPath, args);
child.stderr.setEncoding('utf8');
const checkMessages = common.mustCall(() => {
for (let port = PORT_MIN; port <= PORT_MAX; port += 1) {
assert(stderr.includes(`Debugger listening on 127.0.0.1:${port}`));
}
});
let stderr = '';
child.stderr.on('data', (data) => {
process.stderr.write(`[DATA] ${data}`);
stderr += data;
if (child.killed !== true && stderr.includes('all workers are running')) {
child.kill();
checkMessages();
}
});

63
test/parallel/test-debug-port-from-cmdline.js

@ -1,63 +0,0 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
const os = require('os');
const debugPort = common.PORT;
const args = ['--interactive', '--debug-port=' + debugPort];
const childOptions = { stdio: ['pipe', 'pipe', 'pipe', 'ipc'] };
const child = spawn(process.execPath, args, childOptions);
const reDeprecationWarning = new RegExp(
/^\(node:\d+\) \[DEP0062\] DeprecationWarning: /.source +
/node --debug is deprecated\. /.source +
/Please use node --inspect instead\.$/.source
);
child.stdin.write("process.send({ msg: 'childready' });\n");
child.stderr.on('data', function(data) {
const lines = data.toString().replace(/\r/g, '').trim().split('\n');
lines.forEach(processStderrLine);
});
child.on('message', function onChildMsg(message) {
if (message.msg === 'childready') {
process._debugProcess(child.pid);
}
});
process.on('exit', function() {
child.kill();
assertOutputLines();
});
const outputLines = [];
function processStderrLine(line) {
console.log('> ' + line);
outputLines.push(line);
if (/Debugger listening/.test(line)) {
process.exit();
}
}
function assertOutputLines() {
// need a var so can swap the first two lines in following
// eslint-disable-next-line no-var
var expectedLines = [
/^Starting debugger agent\.$/,
reDeprecationWarning,
new RegExp(`^Debugger listening on 127\\.0\\.0\\.1:${debugPort}$`)
];
if (os.platform() === 'win32') {
expectedLines[1] = expectedLines[0];
expectedLines[0] = reDeprecationWarning;
}
assert.strictEqual(outputLines.length, expectedLines.length);
for (let i = 0; i < expectedLines.length; i++)
assert(expectedLines[i].test(outputLines[i]));
}

59
test/parallel/test-debug-port-numbers.js

@ -1,59 +0,0 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const path = require('path');
const spawn = require('child_process').spawn;
// FIXME(bnoordhuis) On UNIX platforms, the debugger doesn't reliably kill
// the inferior when killed by a signal. Work around that by spawning
// the debugger in its own process group and killing the process group
// instead of just the debugger process.
const detached = !common.isWindows;
const children = [];
for (let i = 0; i < 4; i += 1) {
const port = common.PORT + i;
const args = [`--debug-port=${port}`, '--interactive', 'debug', __filename];
const child = spawn(process.execPath, args, { detached, stdio: 'pipe' });
child.test = { port: port, stdout: '' };
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(s) { child.test.stdout += s; update(); });
child.stdout.pipe(process.stdout);
child.stderr.pipe(process.stderr);
children.push(child);
}
function update() {
// Debugger prints relative paths except on Windows.
const filename = path.basename(__filename);
let ready = 0;
for (const child of children)
ready += RegExp(`break in .*?${filename}:1`).test(child.test.stdout);
if (ready === children.length)
for (const child of children)
kill(child);
}
function kill(child) {
if (!detached)
return child.kill();
try {
process.kill(-child.pid); // Kill process group.
} catch (e) {
// Generally ESRCH is returned when the process group is already gone. On
// some platforms such as OS X it may be EPERM though.
assert.ok((e.code === 'EPERM') || (e.code === 'ESRCH'));
}
}
process.on('exit', function() {
for (const child of children) {
const { port, stdout } = child.test;
assert(stdout.includes(`Debugger listening on 127.0.0.1:${port}`));
assert(stdout.includes(`connecting to 127.0.0.1:${port}`));
}
});

113
test/parallel/test-debug-signal-cluster.js

@ -1,113 +0,0 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
const os = require('os');
const path = require('path');
const port = common.PORT;
const serverPath = path.join(common.fixturesDir, 'clustered-server', 'app.js');
// cannot use 'Flags: --no-deprecation' since it doesn't effect child
const args = [`--debug-port=${port}`, '--no-deprecation', serverPath];
const options = { stdio: ['inherit', 'inherit', 'pipe', 'ipc'] };
const child = spawn(process.execPath, args, options);
let expectedContent = [
'Starting debugger agent.',
'Debugger listening on 127.0.0.1:' + (port + 0),
'Starting debugger agent.',
'Debugger listening on 127.0.0.1:' + (port + 1),
'Starting debugger agent.',
'Debugger listening on 127.0.0.1:' + (port + 2),
].join(os.EOL);
expectedContent += os.EOL; // the last line also contains an EOL character
let debuggerAgentsOutput = '';
let debuggerAgentsStarted = false;
let pids;
child.stderr.on('data', function(data) {
const childStderrOutputString = data.toString();
const lines = childStderrOutputString.replace(/\r/g, '').trim().split('\n');
lines.forEach(function(line) {
console.log('> ' + line);
if (line === 'all workers are running') {
child.on('message', function(msg) {
if (msg.type !== 'pids')
return;
pids = msg.pids;
console.error('got pids %j', pids);
process._debugProcess(child.pid);
debuggerAgentsStarted = true;
});
child.send({
type: 'getpids'
});
}
});
if (debuggerAgentsStarted) {
debuggerAgentsOutput += childStderrOutputString;
if (debuggerAgentsOutput.length === expectedContent.length) {
onNoMoreDebuggerAgentsOutput();
}
}
});
function onNoMoreDebuggerAgentsOutput() {
assertDebuggerAgentsOutput();
process.exit();
}
process.on('exit', function onExit() {
// Kill processes in reverse order to avoid timing problems on Windows where
// the parent process is killed before the children.
pids.reverse().forEach(function(pid) {
process.kill(pid);
});
});
function assertDebuggerAgentsOutput() {
// Workers can take different amout of time to start up, and child processes'
// output may be interleaved arbitrarily. Moreover, child processes' output
// may be written using an arbitrary number of system calls, and no assumption
// on buffering or atomicity of output should be made. Thus, we process the
// output of all child processes' debugger agents character by character, and
// remove each character from the set of expected characters. Once all the
// output from all debugger agents has been processed, we consider that we got
// the content we expected if there's no character left in the initial
// expected content.
debuggerAgentsOutput.split('').forEach(function gotChar(char) {
expectedContent = expectedContent.replace(char, '');
});
assert.strictEqual(expectedContent, '');
}

59
test/parallel/test-debugger-util-regression.js

@ -1,59 +0,0 @@
'use strict';
const common = require('../common');
const path = require('path');
const spawn = require('child_process').spawn;
const assert = require('assert');
const DELAY = common.platformTimeout(200);
const fixture = path.join(
common.fixturesDir,
'debugger-util-regression-fixture.js'
);
const args = [
'debug',
`--port=${common.PORT}`,
fixture
];
const proc = spawn(process.execPath, args, { stdio: 'pipe' });
proc.stdout.setEncoding('utf8');
proc.stderr.setEncoding('utf8');
let stdout = '';
let stderr = '';
proc.stdout.on('data', (data) => stdout += data);
proc.stderr.on('data', (data) => stderr += data);
let nextCount = 0;
let exit = false;
// We look at output periodically. We don't do this in the on('data') as we
// may end up processing partial output. Processing periodically ensures that
// the debugger is in a stable state before we take the next step.
const timer = setInterval(() => {
if (stdout.includes('> 1') && nextCount < 1 ||
stdout.includes('> 2') && nextCount < 2 ||
stdout.includes('> 3') && nextCount < 3 ||
stdout.includes('> 4') && nextCount < 4) {
nextCount++;
proc.stdin.write('n\n');
} else if (!exit && (stdout.includes('< { a: \'b\' }'))) {
exit = true;
proc.stdin.write('.exit\n');
// We can cancel the timer and terminate normally.
clearInterval(timer);
} else if (stdout.includes('program terminated')) {
// Catch edge case present in v4.x
// process will terminate after call to util.inspect
common.fail('the program should not terminate');
}
}, DELAY);
process.on('exit', (code) => {
assert.strictEqual(code, 0, 'the program should exit cleanly');
assert.strictEqual(stdout.includes('{ a: \'b\' }'), true,
'the debugger should print the result of util.inspect');
assert.strictEqual(stderr, '', 'stderr should be empty');
});

45
test/sequential/test-debug-host-port.js

@ -1,45 +0,0 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const spawn = require('child_process').spawn;
let run = common.noop;
function test(args, needle) {
const next = run;
run = () => {
const options = {encoding: 'utf8'};
const proc = spawn(process.execPath, args.concat(['-e', '0']), options);
let stderr = '';
proc.stderr.setEncoding('utf8');
proc.stderr.on('data', (data) => {
stderr += data;
if (stderr.includes(needle)) proc.kill();
});
proc.on('exit', common.mustCall(() => {
assert(stderr.includes(needle));
next();
}));
};
}
test(['--debug-brk'], 'Debugger listening on 127.0.0.1:5858');
test(['--debug-brk=1234'], 'Debugger listening on 127.0.0.1:1234');
test(['--debug-brk=0.0.0.0'], 'Debugger listening on 0.0.0.0:5858');
test(['--debug-brk=0.0.0.0:1234'], 'Debugger listening on 0.0.0.0:1234');
test(['--debug-brk=localhost'], 'Debugger listening on 127.0.0.1:5858');
test(['--debug-brk=localhost:1234'], 'Debugger listening on 127.0.0.1:1234');
if (common.hasIPv6) {
test(['--debug-brk=::'], 'Debug port must be in range 1024 to 65535');
test(['--debug-brk=::0'], 'Debug port must be in range 1024 to 65535');
test(['--debug-brk=::1'], 'Debug port must be in range 1024 to 65535');
test(['--debug-brk=[::]'], 'Debugger listening on [::]:5858');
test(['--debug-brk=[::0]'], 'Debugger listening on [::]:5858');
test(['--debug-brk=[::]:1234'], 'Debugger listening on [::]:1234');
test(['--debug-brk=[::0]:1234'], 'Debugger listening on [::]:1234');
test(['--debug-brk=[::ffff:127.0.0.1]:1234'],
'Debugger listening on [::ffff:127.0.0.1]:1234');
}
run(); // Runs tests in reverse order.

31
test/sequential/test-debugger-debug-brk.js

@ -1,31 +0,0 @@
'use strict';
const common = require('../common');
common.skipIfInspectorDisabled();
const assert = require('assert');
const spawn = require('child_process').spawn;
const script = common.fixturesDir + '/empty.js';
function fail() {
assert(0); // `node --debug-brk script.js` should not quit
}
function test(arg) {
const child = spawn(process.execPath, [arg, script]);
child.on('exit', fail);
// give node time to start up the debugger
setTimeout(function() {
child.removeListener('exit', fail);
child.kill();
}, 2000);
process.on('exit', function() {
assert(child.killed);
});
}
test('--debug-brk');
test('--debug-brk=5959');
test('--inspect-brk');
test('--inspect-brk=9230');
Loading…
Cancel
Save