From 3685d04316fe1542e22460df6b37a007f20c86c8 Mon Sep 17 00:00:00 2001 From: Petros Angelatos Date: Mon, 6 Jun 2016 19:06:49 -0700 Subject: [PATCH 1/2] child-process: add stdio flush testcase with pipes While commit 12274a5 fixed data loss when a readable event handler is attached, the problem still exists when the stdio stream has a piped consumer that doesn't read fast enough. Signed-off-by: Petros Angelatos --- .../test-child-process-flush-stdio.js | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/parallel/test-child-process-flush-stdio.js b/test/parallel/test-child-process-flush-stdio.js index c2cae2069a8ce5..db608e4f6cd75c 100644 --- a/test/parallel/test-child-process-flush-stdio.js +++ b/test/parallel/test-child-process-flush-stdio.js @@ -2,6 +2,7 @@ const cp = require('child_process'); const common = require('../common'); const assert = require('assert'); +const stream = require('stream'); // Windows' `echo` command is a built-in shell command and not an external // executable like on *nix @@ -24,6 +25,7 @@ function spawnWithReadable() { assert.strictEqual(code, 0); assert.strictEqual(signal, null); assert.strictEqual(Buffer.concat(buffer).toString().trim(), '123'); + spawnWithPipe(); })); p.stdout.on('readable', function() { let buf; @@ -31,3 +33,32 @@ function spawnWithReadable() { buffer.push(buf); }); } + +function spawnWithPipe() { + const buffer = []; + const through = new stream.PassThrough(); + const p = cp.spawn('seq', [ '36000' ]); + + const ret = []; + for (let i = 1; i <= 36000; i++) { + ret.push(i); + } + + p.on('close', common.mustCall(function(code, signal) { + assert.strictEqual(code, 0); + assert.strictEqual(signal, null); + assert.strictEqual(Buffer.concat(buffer).toString().trim(), ret.join('\n')); + })); + + p.on('exit', common.mustCall(function() { + setImmediate(function() { + through.on('readable', function() { + let buf; + while (buf = this.read()) + buffer.push(buf); + }); + }); + })); + + p.stdout.pipe(through); +} From 56d66cfc8c9560a5a0a6be56fea2338a7e80f85e Mon Sep 17 00:00:00 2001 From: Petros Angelatos Date: Mon, 6 Jun 2016 19:16:54 -0700 Subject: [PATCH 2/2] test: fix testcase to actually detect regression In order for the testcase to fail, the calls to read() must be done after 'exit' is emitted and after flushStdio has been called. With this change, the testcase will catch any regressions on this issue. Signed-off-by: Petros Angelatos --- test/parallel/test-child-process-flush-stdio.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/parallel/test-child-process-flush-stdio.js b/test/parallel/test-child-process-flush-stdio.js index db608e4f6cd75c..7079525e8522b0 100644 --- a/test/parallel/test-child-process-flush-stdio.js +++ b/test/parallel/test-child-process-flush-stdio.js @@ -28,9 +28,11 @@ function spawnWithReadable() { spawnWithPipe(); })); p.stdout.on('readable', function() { - let buf; - while (buf = this.read()) - buffer.push(buf); + setImmediate(() => { + let buf; + while (buf = this.read()) + buffer.push(buf); + }); }); }