Skip to content

Commit 82d88a8

Browse files
jakecastelliwh0
authored andcommitted
stream: pipeline wait for close before calling the callback
The pipeline should wait for close event to finish before calling the callback. The `finishCount` should not below 0 when calling finish function. Fixes: #51540 Co-authored-by: wh0 <wh0@users.noreply.github.com> PR-URL: #53462 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com>
1 parent 508abfe commit 82d88a8

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

‎lib/internal/streams/pipeline.js‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,10 @@ function pipelineImpl(streams, callback, opts) {
224224
finishImpl(err,--finishCount===0);
225225
}
226226

227+
functionfinishOnlyHandleError(err){
228+
finishImpl(err,false);
229+
}
230+
227231
functionfinishImpl(err,final){
228232
if(err&&(!error||error.code==='ERR_STREAM_PREMATURE_CLOSE')){
229233
error=err;
@@ -273,7 +277,7 @@ function pipelineImpl(streams, callback, opts) {
273277
err.name!=='AbortError'&&
274278
err.code!=='ERR_STREAM_PREMATURE_CLOSE'
275279
){
276-
finish(err);
280+
finishOnlyHandleError(err);
277281
}
278282
}
279283
stream.on('error',onError);
@@ -366,7 +370,7 @@ function pipelineImpl(streams, callback, opts) {
366370
}elseif(isNodeStream(stream)){
367371
if(isReadableNodeStream(ret)){
368372
finishCount+=2;
369-
constcleanup=pipe(ret,stream,finish,{ end });
373+
constcleanup=pipe(ret,stream,finish,finishOnlyHandleError,{ end });
370374
if(isReadable(stream)&&isLastStream){
371375
lastStreamCleanup.push(cleanup);
372376
}
@@ -409,12 +413,12 @@ function pipelineImpl(streams, callback, opts) {
409413
returnret;
410414
}
411415

412-
functionpipe(src,dst,finish,{ end }){
416+
functionpipe(src,dst,finish,finishOnlyHandleError,{ end }){
413417
letended=false;
414418
dst.on('close',()=>{
415419
if(!ended){
416420
// Finish if the destination closes before the source has completed.
417-
finish(newERR_STREAM_PREMATURE_CLOSE());
421+
finishOnlyHandleError(newERR_STREAM_PREMATURE_CLOSE());
418422
}
419423
});
420424

‎test/parallel/test-stream-pipeline.js‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,5 +1664,47 @@ const tsp = require('timers/promises');
16641664
pipeline(r,w,common.mustCall((err)=>{
16651665
assert.strictEqual(err,undefined);
16661666
}));
1667+
}
1668+
1669+
{
1670+
// See https://github.com/nodejs/node/issues/51540 for the following 2 tests
1671+
constsrc=newReadable();
1672+
constdst=newWritable({
1673+
destroy(error,cb){
1674+
// Takes a while to destroy
1675+
setImmediate(cb);
1676+
},
1677+
});
1678+
1679+
pipeline(src,dst,(err)=>{
1680+
assert.strictEqual(src.closed,true);
1681+
assert.strictEqual(dst.closed,true);
1682+
assert.strictEqual(err.message,'problem');
1683+
});
1684+
src.destroy(newError('problem'));
1685+
}
16671686

1687+
{
1688+
constsrc=newReadable();
1689+
constdst=newWritable({
1690+
destroy(error,cb){
1691+
// Takes a while to destroy
1692+
setImmediate(cb);
1693+
},
1694+
});
1695+
constpassThroughs=[];
1696+
for(leti=0;i<10;i++){
1697+
passThroughs.push(newPassThrough());
1698+
}
1699+
1700+
pipeline(src, ...passThroughs,dst,(err)=>{
1701+
assert.strictEqual(src.closed,true);
1702+
assert.strictEqual(dst.closed,true);
1703+
assert.strictEqual(err.message,'problem');
1704+
1705+
for(leti=0;i<passThroughs.length;i++){
1706+
assert.strictEqual(passThroughs[i].closed,true);
1707+
}
1708+
});
1709+
src.destroy(newError('problem'));
16681710
}

0 commit comments

Comments
 (0)