Browse Source

child_process: fix data loss with readable event

This commit prevents child process stdio streams from being
automatically flushed on child process exit/close if a 'readable'
event handler has been attached at the time of exit.

Without this, child process stdio data can be lost if the process
exits quickly and a `read()` (e.g. from a 'readable' handler)
hasn't had the chance to get called yet.

Fixes: https://github.com/nodejs/node/issues/5034
PR-URL: https://github.com/nodejs/node/pull/5036
Reviewed-By: Evan Lucas <evanlucas@me.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
process-exit-stdio-flushing
Brian White 9 years ago
parent
commit
12274a5c1b
  1. 2
      lib/internal/child_process.js
  2. 18
      test/parallel/test-child-process-flush-stdio.js

2
lib/internal/child_process.js

@ -217,7 +217,7 @@ util.inherits(ChildProcess, EventEmitter);
function flushStdio(subprocess) { function flushStdio(subprocess) {
if (subprocess.stdio == null) return; if (subprocess.stdio == null) return;
subprocess.stdio.forEach(function(stream, fd, stdio) { subprocess.stdio.forEach(function(stream, fd, stdio) {
if (!stream || !stream.readable) if (!stream || !stream.readable || stream._readableState.readableListening)
return; return;
stream.resume(); stream.resume();
}); });

18
test/parallel/test-child-process-flush-stdio.js

@ -8,10 +8,22 @@ const p = cp.spawn('echo');
p.on('close', common.mustCall(function(code, signal) { p.on('close', common.mustCall(function(code, signal) {
assert.strictEqual(code, 0); assert.strictEqual(code, 0);
assert.strictEqual(signal, null); assert.strictEqual(signal, null);
spawnWithReadable();
})); }));
p.stdout.read(); p.stdout.read();
setTimeout(function() { function spawnWithReadable() {
p.kill(); const buffer = [];
}, 100); const p = cp.spawn('echo', ['123']);
p.on('close', common.mustCall(function(code, signal) {
assert.strictEqual(code, 0);
assert.strictEqual(signal, null);
assert.strictEqual(Buffer.concat(buffer).toString().trim(), '123');
}));
p.stdout.on('readable', function() {
let buf;
while (buf = this.read())
buffer.push(buf);
});
}

Loading…
Cancel
Save