Browse Source

child_process: preserve argument type

A previous fix for a `maxBuffer` bug resulted in a change to the
argument type for the `data` event on `child.stdin` and `child.stdout`
when using `child_process.exec()`.

This fixes the `maxBuffer` bug in a way that does not have that side
effect.

PR-URL: https://github.com/nodejs/node/pull/7391
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Jackson Tian <shyvo1987@gmail.com>
Fixes: https://github.com/nodejs/node/issues/7342
Refs: https://github.com/nodejs/node/issues/1901
v4.x
Rich Trott 9 years ago
committed by Myles Borins
parent
commit
6a08535dd1
  1. 24
      lib/child_process.js
  2. 16
      test/known_issues/test-child-process-max-buffer.js
  3. 31
      test/parallel/test-child-process-exec-maxBuffer.js
  4. 21
      test/parallel/test-child-process-exec-stdout-stderr-data-string.js
  5. 11
      test/parallel/test-exec-max-buffer.js

24
lib/child_process.js

@ -190,12 +190,12 @@ exports.execFile = function(file /*, args, options, callback*/) {
// merge chunks // merge chunks
var stdout; var stdout;
var stderr; var stderr;
if (!encoding) { if (encoding) {
stdout = Buffer.concat(_stdout);
stderr = Buffer.concat(_stderr);
} else {
stdout = _stdout; stdout = _stdout;
stderr = _stderr; stderr = _stderr;
} else {
stdout = Buffer.concat(_stdout);
stderr = Buffer.concat(_stderr);
} }
if (ex) { if (ex) {
@ -260,16 +260,16 @@ exports.execFile = function(file /*, args, options, callback*/) {
child.stdout.setEncoding(encoding); child.stdout.setEncoding(encoding);
child.stdout.addListener('data', function(chunk) { child.stdout.addListener('data', function(chunk) {
stdoutLen += chunk.length; stdoutLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
if (stdoutLen > options.maxBuffer) { if (stdoutLen > options.maxBuffer) {
ex = new Error('stdout maxBuffer exceeded'); ex = new Error('stdout maxBuffer exceeded');
kill(); kill();
} else { } else {
if (!encoding) if (encoding)
_stdout.push(chunk);
else
_stdout += chunk; _stdout += chunk;
else
_stdout.push(chunk);
} }
}); });
} }
@ -279,16 +279,16 @@ exports.execFile = function(file /*, args, options, callback*/) {
child.stderr.setEncoding(encoding); child.stderr.setEncoding(encoding);
child.stderr.addListener('data', function(chunk) { child.stderr.addListener('data', function(chunk) {
stderrLen += chunk.length; stderrLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
if (stderrLen > options.maxBuffer) { if (stderrLen > options.maxBuffer) {
ex = new Error('stderr maxBuffer exceeded'); ex = new Error('stderr maxBuffer exceeded');
kill(); kill();
} else { } else {
if (!encoding) if (encoding)
_stderr.push(chunk);
else
_stderr += chunk; _stderr += chunk;
else
_stderr.push(chunk);
} }
}); });
} }

16
test/known_issues/test-child-process-max-buffer.js

@ -1,16 +0,0 @@
'use strict';
// Refs: https://github.com/nodejs/node/issues/1901
const common = require('../common');
const assert = require('assert');
const cp = require('child_process');
const unicode = '中文测试'; // Length = 4, Byte length = 13
if (process.argv[2] === 'child') {
console.log(unicode);
} else {
const cmd = `${process.execPath} ${__filename} child`;
cp.exec(cmd, { maxBuffer: 10 }, common.mustCall((err, stdout, stderr) => {
assert.strictEqual(err.message, 'stdout maxBuffer exceeded');
}));
}

31
test/parallel/test-child-process-exec-maxBuffer.js

@ -0,0 +1,31 @@
'use strict';
const common = require('../common');
const assert = require('assert');
const cp = require('child_process');
function checkFactory(streamName) {
return common.mustCall((err) => {
const message = `${streamName} maxBuffer exceeded`;
assert.strictEqual(err.message, message);
});
}
{
const cmd = 'echo "hello world"';
cp.exec(cmd, { maxBuffer: 5 }, checkFactory('stdout'));
}
const unicode = '中文测试'; // length = 4, byte length = 12
{
const cmd = `"${process.execPath}" -e "console.log('${unicode}');"`;
cp.exec(cmd, {maxBuffer: 10}, checkFactory('stdout'));
}
{
const cmd = `"${process.execPath}" -e "console.('${unicode}');"`;
cp.exec(cmd, {maxBuffer: 10}, checkFactory('stderr'));
}

21
test/parallel/test-child-process-exec-stdout-data-string.js → test/parallel/test-child-process-exec-stdout-stderr-data-string.js

@ -4,13 +4,20 @@ const common = require('../common');
const assert = require('assert'); const assert = require('assert');
const exec = require('child_process').exec; const exec = require('child_process').exec;
const expectedCalls = 2; var stdoutCalls = 0;
var stderrCalls = 0;
const cb = common.mustCall((data) => {
assert.strictEqual(typeof data, 'string');
}, expectedCalls);
const command = common.isWindows ? 'dir' : 'ls'; const command = common.isWindows ? 'dir' : 'ls';
exec(command).stdout.on('data', cb); exec(command).stdout.on('data', (data) => {
stdoutCalls += 1;
});
exec('fhqwhgads').stderr.on('data', (data) => {
assert.strictEqual(typeof data, 'string');
stderrCalls += 1;
});
exec('fhqwhgads').stderr.on('data', cb); process.on('exit', () => {
assert(stdoutCalls > 0);
assert(stderrCalls > 0);
});

11
test/parallel/test-exec-max-buffer.js

@ -1,11 +0,0 @@
'use strict';
require('../common');
var exec = require('child_process').exec;
var assert = require('assert');
var cmd = 'echo "hello world"';
exec(cmd, { maxBuffer: 5 }, function(err, stdout, stderr) {
assert.ok(err);
assert.ok(/maxBuffer/.test(err.message));
});
Loading…
Cancel
Save