Repository navigation
Readable streams with highWaterMark: 0 terminate early #24915
Description
Activity
The following is based on visual inspection on the code. I didn't actually debug through anything, so it could just as well be full of mistakes.
Looking further into this.
The case where
_readpushes data synchronously is taken care of by the while-loop inflow(stream). As long as_read()pushes data, thestream.read()will return non-null result and that while loop continues.If
_readpushes data asynchronously, it callsReadable.pushat some point. This results in the following call stack:Readable.push(chunk, encoding)calls...readableAddChunk(stream, chunk, ...)calls...addChunk(stream, state, ...)calls...maybeReadMore(stream, state)
maybeReadMore_has a while-loop that callsstream.read(), but only ifstate.length < state.highWaterMark.As far as I can tell,
maybeReadMoreis used in both the flowing and paused modes. In paused mode that check seems correct: The stream should not pre-emptively request more data from the implementation but instead wait for calls to.read(). However in the flowing mode that check should take into account that it is responsible for providing data for thedataevent to emit.I guess the correct fix would be to calculate a
bufferLimitto account for the first item being consumed immediately:let bufferLimit = state.highWaterMark; if (state.flowing) bufferLimit += 1;
Or alternatively match the
addChunkif-check and add a similar condition to the while-loop inmaybeReadMore_:while (!state.reading && !state.ended && (state.length < state.highWaterMark || state.flowing && state.length === 0 && !state.sync)) {
(Not sure whether the
state.syncis required)Forcing
highWaterMark > 0is a really ugly workaround for this for the cases where the stream is coming from a library and it isn't possible to change thehighWaterMarkin the constructor.someStream._readableState.highWaterMark = 1;
... and I'm now looking into fixing this. Should have a PR up later today.
- addedstreamIssues and PRs related to Node.js streams.Issues and PRs related to Node.js streams.
on Dec 9, 2018 - added a commit that references this issue
on Dec 14, 2018 Fixed in 37a5e01
- added a commit that references this issue
on Dec 18, 2018 - added a commit that references this issue
on Jan 14, 2019 - added a commit that references this issue
on Feb 12, 2019 - added a commit that references this issue
on Feb 20, 2019 - added a commit that references this issue
on Feb 28, 2019
#20503 fixed things with
highWaterMark: 0streams. As far as I could tell, this was merged into v10.9.0.However the following code still fails in v10.10.0 and v11.4.0:
The
MyStreamimplementation is supposed to continue emitting 'a' without terminating. However the output of that is:If I change the constructor into
{ highWaterMark: 1 }I get the expected infinite push/data cycle.