From 8b65aa73f628b971cb11663c4ba73e17a649a465 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Fri, 15 Mar 2019 20:23:15 +0100 Subject: [PATCH] process: make stdout and stderr emit 'close' on destroy Fix: https://github.com/nodejs/node/issues/26550 PR-URL: https://github.com/nodejs/node/pull/26691 Fixes: https://github.com/false Fixes: https://github.com/nodejs/node/issues/26550 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen --- lib/internal/process/stdio.js | 21 ++++++++++++- test/parallel/test-stdout-pipeline-destroy.js | 31 +++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 test/parallel/test-stdout-pipeline-destroy.js diff --git a/lib/internal/process/stdio.js b/lib/internal/process/stdio.js index bf5f6df15f123c..46c2ba4e9ca35d 100644 --- a/lib/internal/process/stdio.js +++ b/lib/internal/process/stdio.js @@ -2,7 +2,26 @@ exports.getMainThreadStdio = getMainThreadStdio; -function dummyDestroy(err, cb) { cb(err); } +function dummyDestroy(err, cb) { + // SyncWriteStream does not use the stream + // destroy mechanism for some legacy reason. + // TODO(mcollina): remove when + // https://github.com/nodejs/node/pull/26690 lands. + if (typeof cb === 'function') { + cb(err); + } + + // We need to emit 'close' anyway so that the closing + // of the stream is observable. We just make sure we + // are not going to do it twice. + // The 'close' event is needed so that finished and + // pipeline work correctly. + if (!this._writableState.emitClose) { + process.nextTick(() => { + this.emit('close'); + }); + } +} function getMainThreadStdio() { var stdin; diff --git a/test/parallel/test-stdout-pipeline-destroy.js b/test/parallel/test-stdout-pipeline-destroy.js new file mode 100644 index 00000000000000..291579cf69d3d4 --- /dev/null +++ b/test/parallel/test-stdout-pipeline-destroy.js @@ -0,0 +1,31 @@ +'use strict'; + +const common = require('../common'); +const { Transform, Readable, pipeline } = require('stream'); +const assert = require('assert'); + +const reader = new Readable({ + read(size) { this.push('foo'); } +}); + +let count = 0; + +const err = new Error('this-error-gets-hidden'); + +const transform = new Transform({ + transform(chunk, enc, cb) { + if (count++ >= 5) + this.emit('error', err); + else + cb(null, count.toString() + '\n'); + } +}); + +pipeline( + reader, + transform, + process.stdout, + common.mustCall((e) => { + assert.strictEqual(e, err); + }) +);