Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
stream: do not unconditionally call _read() on resume()
`readable.resume()` calls `.read(0)`, which in turn previously set
`needReadable = true`, and so a subsequent `.read()` call would
call `_read()` even though enough data was already available.

This can lead to elevated memory usage, because calling `_read()`
when enough data is in the readable buffer means that backpressure
is not being honoured.

Fixes: #26957
  • Loading branch information
addaleax committed Mar 28, 2019
commit 5c72c6d2028866409b1dd17ba70825d8eeb07c87
2 changes: 1 addition & 1 deletion lib/_stream_readable.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ Readable.prototype.read = function(n) {
ret = null;

if (ret === null) {
state.needReadable = true;
state.needReadable = state.length <= state.highWaterMark;
n = 0;
} else {
state.length -= n;
Expand Down
21 changes: 21 additions & 0 deletions test/parallel/test-stream-readable-resume-hwm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';
const common = require('../common');
const { Readable } = require('stream');

// readable.resume() should not lead to a ._read() call being scheduled
// when we exceed the high water mark already.

const readable = new Readable({
read: common.mustNotCall(),
highWaterMark: 100
});

// Fill up the internal buffer so that we definitely exceed the HWM:
for (let i = 0; i < 10; i++)
readable.push('a'.repeat(200));

// Call resume, and pause after one chunk.
// The .pause() is just so that we don’t empty the buffer fully, which would
// be a valid reason to call ._read().
readable.resume();
readable.once('data', common.mustCall(() => readable.pause()));