Skip to content

Commit 184e80a

Browse files
ronagBethGriggs
authored andcommitted
stream: don't wait for close on legacy streams
Try to detect non standard streams and don't wait for 'close' on these. In particular if we detected that destroyed is true before we expect it to be then fallback to compat behavior. Fixes: #33050 PR-URL: #33058 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Zeyu Yang <himself65@outlook.com>
1 parent fad188f commit 184e80a

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

lib/internal/streams/end-of-stream.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function eos(stream, opts, callback) {
7272
// TODO (ronag): Improve soft detection to include core modules and
7373
// common ecosystem modules that do properly emit 'close' but fail
7474
// this generic check.
75-
const willEmitClose = (
75+
let willEmitClose = (
7676
state &&
7777
state.autoDestroy &&
7878
state.emitClose &&
@@ -85,6 +85,11 @@ function eos(stream, opts, callback) {
8585
(wState && wState.finished);
8686
const onfinish = () => {
8787
writableFinished = true;
88+
// Stream should not be destroyed here. If it is that
89+
// means that user space is doing something differently and
90+
// we cannot trust willEmitClose.
91+
if (stream.destroyed) willEmitClose = false;
92+
8893
if (willEmitClose && (!stream.readable || readable)) return;
8994
if (!readable || readableEnded) callback.call(stream);
9095
};
@@ -93,6 +98,11 @@ function eos(stream, opts, callback) {
9398
(rState && rState.endEmitted);
9499
const onend = () => {
95100
readableEnded = true;
101+
// Stream should not be destroyed here. If it is that
102+
// means that user space is doing something differently and
103+
// we cannot trust willEmitClose.
104+
if (stream.destroyed) willEmitClose = false;
105+
96106
if (willEmitClose && (!stream.writable || writable)) return;
97107
if (!writable || writableFinished) callback.call(stream);
98108
};

test/parallel/test-stream-finished.js

+12
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,15 @@ testClosed((opts) => new Writable({ write() {}, ...opts }));
384384

385385
d.resume();
386386
}
387+
388+
{
389+
// Test for compat for e.g. fd-slicer which implements
390+
// non standard destroy behavior which might not emit
391+
// 'close'.
392+
const r = new Readable();
393+
finished(r, common.mustCall());
394+
r.resume();
395+
r.push('asd');
396+
r.destroyed = true;
397+
r.push(null);
398+
}

0 commit comments

Comments
 (0)