summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremiah Senkpiel <fishrock123@rocketmail.com>2018-12-10 16:34:32 -0800
committerJeremiah Senkpiel <fishrock123@rocketmail.com>2019-01-23 15:45:46 -0800
commite47f972d6851b3196b3b2ba611929f25a5fcadb6 (patch)
tree029dfbf0f302224763c6e541d0909b86c87ef0c6
parent5f866821adf71ff3ed909d4be8c808197663c110 (diff)
downloadandroid-node-v8-e47f972d6851b3196b3b2ba611929f25a5fcadb6.tar.gz
android-node-v8-e47f972d6851b3196b3b2ba611929f25a5fcadb6.tar.bz2
android-node-v8-e47f972d6851b3196b3b2ba611929f25a5fcadb6.zip
child_process: truncate output when maxBuffer is exceeded
Preserves truncated output for `child_process.exec()` when `maxBuffer` is exceeded. This is particularly useful for commands which have indistinguishable error codes for what output they produce. PR-URL: https://github.com/nodejs/node/pull/24951 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: Anna Henningsen <anna@addaleax.net>
-rw-r--r--doc/api/child_process.md20
-rw-r--r--lib/child_process.js16
-rw-r--r--test/parallel/test-child-process-exec-maxBuffer.js25
3 files changed, 45 insertions, 16 deletions
diff --git a/doc/api/child_process.md b/doc/api/child_process.md
index e32568cd78..cdfdab1a98 100644
--- a/doc/api/child_process.md
+++ b/doc/api/child_process.md
@@ -147,8 +147,9 @@ changes:
`'/bin/sh'` on UNIX, `process.env.ComSpec` on Windows.
* `timeout` {number} **Default:** `0`
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
- stderr. If exceeded, the child process is terminated. See caveat at
- [`maxBuffer` and Unicode][]. **Default:** `200 * 1024`.
+ stderr. If exceeded, the child process is terminated and any output is
+ truncated. See caveat at [`maxBuffer` and Unicode][].
+ **Default:** `200 * 1024`.
* `killSignal` {string|integer} **Default:** `'SIGTERM'`
* `uid` {number} Sets the user identity of the process (see setuid(2)).
* `gid` {number} Sets the group identity of the process (see setgid(2)).
@@ -245,8 +246,9 @@ changes:
* `encoding` {string} **Default:** `'utf8'`
* `timeout` {number} **Default:** `0`
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
- stderr. If exceeded, the child process is terminated. See caveat at
- [`maxBuffer` and Unicode][]. **Default:** `200 * 1024`.
+ stderr. If exceeded, the child process is terminated and any output is
+ truncated. See caveat at [`maxBuffer` and Unicode][].
+ **Default:** `200 * 1024`.
* `killSignal` {string|integer} **Default:** `'SIGTERM'`
* `uid` {number} Sets the user identity of the process (see setuid(2)).
* `gid` {number} Sets the group identity of the process (see setgid(2)).
@@ -779,8 +781,9 @@ changes:
* `killSignal` {string|integer} The signal value to be used when the spawned
process will be killed. **Default:** `'SIGTERM'`.
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
- stderr. If exceeded, the child process is terminated. See caveat at
- [`maxBuffer` and Unicode][]. **Default:** `200 * 1024`.
+ stderr. If exceeded, the child process is terminated and any output is
+ truncated. See caveat at [`maxBuffer` and Unicode][].
+ **Default:** `200 * 1024`.
* `encoding` {string} The encoding used for all stdio inputs and outputs.
**Default:** `'buffer'`.
* `windowsHide` {boolean} Hide the subprocess console window that would
@@ -842,8 +845,9 @@ changes:
* `killSignal` {string|integer} The signal value to be used when the spawned
process will be killed. **Default:** `'SIGTERM'`.
* `maxBuffer` {number} Largest amount of data in bytes allowed on stdout or
- stderr. If exceeded, the child process is terminated. See caveat at
- [`maxBuffer` and Unicode][]. **Default:** `200 * 1024`.
+ stderr. If exceeded, the child process is terminated and any output is
+ truncated. See caveat at [`maxBuffer` and Unicode][].
+ **Default:** `200 * 1024`.
* `encoding` {string} The encoding used for all stdio inputs and outputs.
**Default:** `'buffer'`.
* `shell` {boolean|string} If `true`, runs `command` inside of a shell. Uses
diff --git a/lib/child_process.js b/lib/child_process.js
index d70803866c..8060412b3f 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -343,9 +343,15 @@ exports.execFile = function execFile(file /* , args, options, callback */) {
child.stdout.on('data', function onChildStdout(chunk) {
var encoding = child.stdout._readableState.encoding;
- stdoutLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
+ const length = encoding ?
+ Buffer.byteLength(chunk, encoding) :
+ chunk.length;
+ stdoutLen += length;
if (stdoutLen > options.maxBuffer) {
+ const truncatedLen = options.maxBuffer - (stdoutLen - length);
+ _stdout.push(chunk.slice(0, truncatedLen));
+
ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER('stdout');
kill();
} else {
@@ -360,9 +366,15 @@ exports.execFile = function execFile(file /* , args, options, callback */) {
child.stderr.on('data', function onChildStderr(chunk) {
var encoding = child.stderr._readableState.encoding;
- stderrLen += encoding ? Buffer.byteLength(chunk, encoding) : chunk.length;
+ const length = encoding ?
+ Buffer.byteLength(chunk, encoding) :
+ chunk.length;
+ stderrLen += length;
if (stderrLen > options.maxBuffer) {
+ const truncatedLen = options.maxBuffer - (stderrLen - length);
+ _stderr.push(chunk.slice(0, truncatedLen));
+
ex = new ERR_CHILD_PROCESS_STDIO_MAXBUFFER('stderr');
kill();
} else {
diff --git a/test/parallel/test-child-process-exec-maxBuffer.js b/test/parallel/test-child-process-exec-maxBuffer.js
index 569efb5deb..dfa46b0b00 100644
--- a/test/parallel/test-child-process-exec-maxBuffer.js
+++ b/test/parallel/test-child-process-exec-maxBuffer.js
@@ -22,13 +22,13 @@ function runChecks(err, stdio, streamName, expected) {
}
{
- const cmd = 'echo "hello world"';
+ const cmd = 'echo hello world';
cp.exec(
cmd,
{ maxBuffer: 5 },
common.mustCall((err, stdout, stderr) => {
- runChecks(err, { stdout, stderr }, 'stdout', '');
+ runChecks(err, { stdout, stderr }, 'stdout', 'hello');
})
);
}
@@ -42,7 +42,7 @@ const unicode = '中文测试'; // length = 4, byte length = 12
cmd,
{ maxBuffer: 10 },
common.mustCall((err, stdout, stderr) => {
- runChecks(err, { stdout, stderr }, 'stdout', '');
+ runChecks(err, { stdout, stderr }, 'stdout', '中文测试\n');
})
);
}
@@ -54,7 +54,7 @@ const unicode = '中文测试'; // length = 4, byte length = 12
cmd,
{ maxBuffer: 3 },
common.mustCall((err, stdout, stderr) => {
- runChecks(err, { stdout, stderr }, 'stderr', '');
+ runChecks(err, { stdout, stderr }, 'stderr', '中文测');
})
);
}
@@ -66,7 +66,7 @@ const unicode = '中文测试'; // length = 4, byte length = 12
cmd,
{ encoding: null, maxBuffer: 10 },
common.mustCall((err, stdout, stderr) => {
- runChecks(err, { stdout, stderr }, 'stdout', '');
+ runChecks(err, { stdout, stderr }, 'stdout', '中文测试\n');
})
);
@@ -80,9 +80,22 @@ const unicode = '中文测试'; // length = 4, byte length = 12
cmd,
{ encoding: null, maxBuffer: 3 },
common.mustCall((err, stdout, stderr) => {
- runChecks(err, { stdout, stderr }, 'stderr', '');
+ runChecks(err, { stdout, stderr }, 'stderr', '中文测');
})
);
child.stderr.setEncoding('utf-8');
}
+
+{
+ const cmd = `"${process.execPath}" -e "console.error('${unicode}');"`;
+
+ cp.exec(
+ cmd,
+ { encoding: null, maxBuffer: 5 },
+ common.mustCall((err, stdout, stderr) => {
+ const buf = Buffer.from(unicode).slice(0, 5);
+ runChecks(err, { stdout, stderr }, 'stderr', buf);
+ })
+ );
+}