From 94f52b531c04181806b5f61d3ce457b9cc966a34 Mon Sep 17 00:00:00 2001 From: Remy Sharp Date: Tue, 9 Jan 2018 09:26:45 +0000 Subject: [PATCH] fix: node < 6.4.0 can't connect to stdin Fixes #1218 --- lib/monitor/run.js | 47 ++++++++++++++++++++++------------------------ lib/spawn.js | 29 +++++++++++----------------- lib/utils/index.js | 3 +++ 3 files changed, 36 insertions(+), 43 deletions(-) diff --git a/lib/monitor/run.js b/lib/monitor/run.js index 0e9a6440..b39908de 100644 --- a/lib/monitor/run.js +++ b/lib/monitor/run.js @@ -68,24 +68,22 @@ function run(options) { var args = runCmd ? utils.stringify(executable, cmd.args) : ':'; var spawnArgs = [sh, [shFlag, args]]; - if (utils.version.major === 0 && utils.version.minor < 8) { - // use the old spawn args :-\ - } else { - spawnArgs.push({ - env: utils.merge(options.execOptions.env, process.env), - stdio: stdio, - }); - } + spawnArgs.push({ + env: utils.merge(options.execOptions.env, process.env), + stdio: stdio, + }); const firstArg = cmd.args[0] || ''; + // hasStdio allows us to correctly handle stdin piping + // see: https://git.io/vNtX3 + const hasStdio = utils.satisfies('>= 6.4.0'); + if ( - // this is a hack to avoid forking if there's a node argument being passed - // it's a short term fix, and I'm not 100% sure that `fork` is the right way - firstArg.indexOf('-') === -1 && - firstArg !== 'inspect' && - executable === 'node' && - utils.version.major > 4 + firstArg.indexOf('-') === -1 && // don't fork if there's a node arg + firstArg !== 'inspect' && // don't fork it's `inspect` debugger + executable === 'node' && // only fork if node + utils.version.major > 4 // only fork if node version > 4 ) { var forkArgs = cmd.args.slice(1); var env = utils.merge(options.execOptions.env, process.env); @@ -93,6 +91,7 @@ function run(options) { child = fork(options.execOptions.script, forkArgs, { env: env, stdio: stdio, + silent: !hasStdio, }); utils.log.detail('forking'); debug(forkArgs); @@ -217,9 +216,7 @@ function run(options) { // if the stdin piping is on, we need to unpipe, but also close stdin on // the child, otherwise linux can throw EPIPE or ECONNRESET errors. if (options.stdin) { - if (process.stdin.unpipe) { // node > 0.8 - process.stdin.unpipe(child.stdin); - } + process.stdin.unpipe(child.stdin); } if (utils.isWindows) { @@ -235,12 +232,8 @@ function run(options) { // this seems to fix the 0.11.x issue with the "rs" restart command, // though I'm unsure why. it seems like more data is streamed in to // stdin after we close. - if (child && options.stdin && oldPid === child.pid) { - // this is stupid and horrible, but node 0.12 on windows blows up - // with this line, so we'll skip it entirely. - if (!utils.isWindows) { - child.stdin.end(); - } + if (child && options.stdin && child.stdin && oldPid === child.pid) { + child.stdin.end(); } callback(); }); @@ -264,8 +257,12 @@ function run(options) { // swallow the stdin error if it happens // ref: https://github.com/remy/nodemon/issues/1195 - child.stdin.on('error', () => {}); - process.stdin.pipe(child.stdin); + if (hasStdio) { + child.stdin.on('error', () => { }); + process.stdin.pipe(child.stdin); + } else { + child.stdout.pipe(process.stdout); + } bus.once('exit', function () { if (child && process.stdin.unpipe) { // node > 0.8 diff --git a/lib/spawn.js b/lib/spawn.js index e098f213..a27936cc 100644 --- a/lib/spawn.js +++ b/lib/spawn.js @@ -1,12 +1,10 @@ -var utils = require('./utils'); -var merge = utils.merge; -var bus = utils.bus; -var childProcess = require('child_process'); -var _spawn = childProcess.spawn; +const utils = require('./utils'); +const merge = utils.merge; +const bus = utils.bus; +const spawn = require('child_process').spawn; -module.exports = function spawn(command, config, eventArgs) { +module.exports = function spawnCommand(command, config, eventArgs) { var stdio = ['pipe', 'pipe', 'pipe']; - var child = null; if (config.options.stdout) { stdio = ['pipe', process.stdout, process.stderr]; @@ -20,23 +18,18 @@ module.exports = function spawn(command, config, eventArgs) { shFlag = '/c'; } - var args = ''; if (!Array.isArray(command)) { command = [command]; } - args = command.join(' '); + const args = command.join(' '); - if (utils.version.major >= 1 || utils.version.minor >= 8) { - var env = merge(process.env, { FILENAME: eventArgs[0] }); - child = _spawn(sh, [shFlag, args], { - env: merge(config.options.execOptions.env, env), - stdio: stdio, - }); - } else { - child = spawn(sh, args); - } + const env = merge(process.env, { FILENAME: eventArgs[0] }); + const child = _spawn(sh, [shFlag, args], { + env: merge(config.options.execOptions.env, env), + stdio: stdio, + }); if (config.required) { var emit = { diff --git a/lib/utils/index.js b/lib/utils/index.js index b6cde7b5..5f1f857b 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -1,8 +1,11 @@ var noop = function () { }; var path = require('path'); +const semver = require('semver'); var version = process.versions.node.split('.') || [null, null, null]; var utils = (module.exports = { + semver: semver, + satisfies: test => semver.satisfies(process.versions.node, test), version: { major: parseInt(version[0] || 0, 10), minor: parseInt(version[1] || 0, 10),