From fab8c83253e3e4a313c12fea43021e0d2e507cef Mon Sep 17 00:00:00 2001 From: Robert Nagy Date: Wed, 11 Mar 2020 13:56:24 +0100 Subject: [PATCH] stream: avoid destroying writable source User might still want to be able to use the writable side of src. This is in the case where e.g. the Duplex input is not directly connected to its output. Such a case could happen when the Duplex is reading from a socket and then echos the data back on the same socket. Backport-PR-URL: https://github.com/nodejs/node/pull/32212 PR-URL: https://github.com/nodejs/node/pull/32198 Refs: https://github.com/nodejs/node/commit/4d93e105bfad79ff6c6f01e4b7c2fdd70caeb43b#commitcomment-37751035 Reviewed-By: James M Snell Reviewed-By: Matteo Collina --- lib/internal/streams/pipeline.js | 4 ++++ test/parallel/test-stream-pipeline.js | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/lib/internal/streams/pipeline.js b/lib/internal/streams/pipeline.js index 7499e37c7b7afb..493a464d07b295 100644 --- a/lib/internal/streams/pipeline.js +++ b/lib/internal/streams/pipeline.js @@ -57,6 +57,10 @@ function destroyer(stream, reading, writing, final, callback) { return callback(); } + if (!err && reading && !writing && stream.writable) { + return callback(); + } + if (err || !final || !stream.readable) { destroyImpl.destroyer(stream, err); } diff --git a/test/parallel/test-stream-pipeline.js b/test/parallel/test-stream-pipeline.js index 17532854f974fd..5175b7e07c53c2 100644 --- a/test/parallel/test-stream-pipeline.js +++ b/test/parallel/test-stream-pipeline.js @@ -1016,3 +1016,19 @@ const { promisify } = require('util'); req.on('error', common.mustNotCall()); }); } + +{ + // Might still want to be able to use the writable side + // of src. This is in the case where e.g. the Duplex input + // is not directly connected to its output. Such a case could + // happen when the Duplex is reading from a socket and then echos + // the data back on the same socket. + const src = new PassThrough(); + assert.strictEqual(src.writable, true); + const dst = new PassThrough(); + pipeline(src, dst, common.mustCall((err) => { + assert.strictEqual(src.writable, true); + assert.strictEqual(src.destroyed, false); + })); + src.push(null); +}