Skip to content

Commit 1c47bba

Browse files
ronagtargos
authored andcommitted
stream: complete pipeline with stdio
stdio (stderr & stdout) should for compatibility reasons not be closed/end():ed. However, this causes pipeline with a stdio destination to never finish. This commit fixes this issue at a performance cost. Refs: #7606 Fixes: #32363 PR-URL: #32373 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 9df274a commit 1c47bba

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

lib/internal/streams/pipeline.js

+7
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ function pipeline(...streams) {
255255
} else if (isStream(stream)) {
256256
if (isReadable(ret)) {
257257
ret.pipe(stream);
258+
259+
// Compat. Before node v10.12.0 stdio used to throw an error so
260+
// pipe() did/does not end() stdio destinations.
261+
// Now they allow it but "secretly" don't close the underlying fd.
262+
if (stream === process.stdout || stream === process.stderr) {
263+
ret.on('end', () => stream.end());
264+
}
258265
} else {
259266
ret = makeAsyncIterable(ret);
260267

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const os = require('os');
6+
7+
if (process.argv[2] === 'child') {
8+
const { pipeline } = require('stream');
9+
pipeline(
10+
process.stdin,
11+
process.stdout,
12+
common.mustCall((err) => {
13+
assert.ifError(err);
14+
})
15+
);
16+
} else {
17+
const cp = require('child_process');
18+
cp.exec([
19+
'echo',
20+
'hello',
21+
'|',
22+
`"${process.execPath}"`,
23+
`"${__filename}"`,
24+
'child'
25+
].join(' '), common.mustCall((err, stdout) => {
26+
assert.ifError(err);
27+
assert.strictEqual(stdout.split(os.EOL).shift().trim(), 'hello');
28+
}));
29+
}

0 commit comments

Comments
 (0)