-
Notifications
You must be signed in to change notification settings - Fork 30k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
child_process: only stop readable side of stream passed to proc
Closing the underlying resource completely has the unwanted side effect that the stream can no longer be used at all, including passing it to other child processes. What we want to avoid is accidentally reading from the stream; accordingly, it should be sufficient to stop its readable side manually, and otherwise leave the underlying resource intact. Fixes: #27097 Refs: #21209 PR-URL: #27373 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Gireesh Punathil <[email protected]>
- Loading branch information
Showing
5 changed files
with
81 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
test/parallel/test-child-process-stdio-merge-stdouts-into-cat.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const { spawn } = require('child_process'); | ||
|
||
// Regression test for https://github.com/nodejs/node/issues/27097. | ||
// Check that (cat [p1] ; cat [p2]) | cat [p3] works. | ||
|
||
const p3 = spawn('cat', { stdio: ['pipe', 'pipe', 'inherit'] }); | ||
const p1 = spawn('cat', { stdio: ['pipe', p3.stdin, 'inherit'] }); | ||
const p2 = spawn('cat', { stdio: ['pipe', p3.stdin, 'inherit'] }); | ||
p3.stdout.setEncoding('utf8'); | ||
|
||
// Write three different chunks: | ||
// - 'hello' from this process to p1 to p3 back to us | ||
// - 'world' from this process to p2 to p3 back to us | ||
// - 'foobar' from this process to p3 back to us | ||
// Do so sequentially in order to avoid race conditions. | ||
p1.stdin.end('hello\n'); | ||
p3.stdout.once('data', common.mustCall((chunk) => { | ||
assert.strictEqual(chunk, 'hello\n'); | ||
p2.stdin.end('world\n'); | ||
p3.stdout.once('data', common.mustCall((chunk) => { | ||
assert.strictEqual(chunk, 'world\n'); | ||
p3.stdin.end('foobar\n'); | ||
p3.stdout.once('data', common.mustCall((chunk) => { | ||
assert.strictEqual(chunk, 'foobar\n'); | ||
})); | ||
})); | ||
})); |
27 changes: 27 additions & 0 deletions
27
test/parallel/test-child-process-stdio-reuse-readable-stdio.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const { spawn } = require('child_process'); | ||
|
||
// Check that, once a child process has ended, it’s safe to read from a pipe | ||
// that the child had used as input. | ||
// We simulate that using cat | (head -n1; ...) | ||
|
||
const p1 = spawn('cat', { stdio: ['pipe', 'pipe', 'inherit'] }); | ||
const p2 = spawn('head', ['-n1'], { stdio: [p1.stdout, 'pipe', 'inherit'] }); | ||
|
||
// First, write the line that gets passed through p2, making 'head' exit. | ||
p1.stdin.write('hello\n'); | ||
p2.stdout.setEncoding('utf8'); | ||
p2.stdout.on('data', common.mustCall((chunk) => { | ||
assert.strictEqual(chunk, 'hello\n'); | ||
})); | ||
p2.on('exit', common.mustCall(() => { | ||
// We can now use cat’s output, because 'head' is no longer reading from it. | ||
p1.stdin.end('world\n'); | ||
p1.stdout.setEncoding('utf8'); | ||
p1.stdout.on('data', common.mustCall((chunk) => { | ||
assert.strictEqual(chunk, 'world\n'); | ||
})); | ||
p1.stdout.resume(); | ||
})); |