Skip to content

Commit daeb21d

Browse files
ronagjuanarbol
authored andcommitted
stream: fix deadlock when pipeing to full sink
When piping a paused Readable to a full Writable we didn't register a drain listener which cause the src to never resume. Refs: #48666 PR-URL: #48691 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 69b55d2 commit daeb21d

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

lib/internal/streams/readable.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -833,9 +833,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) {
833833
// Start the flow if it hasn't been started already.
834834

835835
if (dest.writableNeedDrain === true) {
836-
if (state.flowing) {
837-
pause();
838-
}
836+
pause();
839837
} else if (!state.flowing) {
840838
debug('pipe resume');
841839
src.resume();
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const { Readable, Writable } = require('stream');
5+
6+
// https://github.com/nodejs/node/issues/48666
7+
(async () => {
8+
// Prepare src that is internally ended, with buffered data pending
9+
const src = new Readable({ read() {} });
10+
src.push(Buffer.alloc(100));
11+
src.push(null);
12+
src.pause();
13+
14+
// Give it time to settle
15+
await new Promise((resolve) => setImmediate(resolve));
16+
17+
const dst = new Writable({
18+
highWaterMark: 1000,
19+
write(buf, enc, cb) {
20+
process.nextTick(cb);
21+
}
22+
});
23+
24+
dst.write(Buffer.alloc(1000)); // Fill write buffer
25+
dst.on('finish', common.mustCall());
26+
src.pipe(dst);
27+
})().then(common.mustCall());

0 commit comments

Comments
 (0)