'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 = child.test.port; const one = RegExp(`Debugger listening on (\\[::\\]|0\.0\.0\.0):${port}`); const two = RegExp(`connecting to 127.0.0.1:${port}`); assert(one.test(child.test.stdout)); assert(two.test(child.test.stdout)); } });