Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stream: regression in v14, this.push(null) in Transform doesn't emit end #35926

Closed
rlidwka opened this issue Nov 2, 2020 · 7 comments · Fixed by #35941
Closed

stream: regression in v14, this.push(null) in Transform doesn't emit end #35926

rlidwka opened this issue Nov 2, 2020 · 7 comments · Fixed by #35941
Labels
confirmed-bug Issues with confirmed bugs. stream Issues and PRs related to the stream subsystem.

Comments

@rlidwka
Copy link
Contributor

rlidwka commented Nov 2, 2020

  • Version: v14.5.0
  • Platform: Ubuntu/Linux
  • Subsystem: stream
let stream = require('stream');

let src = new stream.Readable({
  read() {
    console.log('push')
    this.push(Buffer.alloc(20000));
  }
});

let dst = new stream.Transform({
  transform(chunk, output, fn) {
    this.push(null);
    fn();
  }
});

src.pipe(dst);

function parser_end(error) {
  console.log('parser ended', error);
  dst.removeAllListeners();
}

dst.once('data', data => console.log(data));
dst.once('end', () => parser_end());
dst.on('error', error => parser_end(error));
  • Expected behavior (tested on node v10, 12): end event is emitted by dst, transform stops, source pauses.
  • Actual behavior (tested on node v14): end event does not get emitted by dst, transform runs indefinitely.
@lpinca lpinca added the stream Issues and PRs related to the stream subsystem. label Nov 2, 2020
@lpinca
Copy link
Member

lpinca commented Nov 2, 2020

@nodejs/streams @ronag

@mcollina mcollina added the confirmed-bug Issues with confirmed bugs. label Nov 2, 2020
@mcollina
Copy link
Member

mcollina commented Nov 2, 2020

Confirmed, this is a bug, just tested in the latest v14 and on master.

@ronag
Copy link
Member

ronag commented Nov 2, 2020

In this case... shouldn't it actually fail with ERR_STREAM_WRITE_AFTER_END since pipe will continue writing?

If find this case quite problematic.

@puzrin
Copy link

puzrin commented Nov 3, 2020

In this case... shouldn't it actually fail with ERR_STREAM_WRITE_AFTER_END since pipe will continue writing?

Problem is data not processed in consumer at all. Handlers, which have to call end/destroy are not reached. Looks like data buffered somewhere until stream end.

https://github.com/nodeca/probe-image-size/blob/master/stream.js - full source if anyone interested.

The same with generator-based source:

async function * generate() {
  for (;;) {
    yield Buffer.alloc(20000);
  }
}

let src = Readable.from(generate());

@mcollina
Copy link
Member

mcollina commented Nov 3, 2020

In this case... shouldn't it actually fail with ERR_STREAM_WRITE_AFTER_END since pipe will continue writing?

No. .pipe() historically automatically unpiped from the source if the destination ended, i.e. the source is not paused while it should be.

I think we'd need to bisect this if you do not have a suspect.

@ronag
Copy link
Member

ronag commented Nov 3, 2020

I think we'd need to bisect this if you do not have a suspect.

Haven't started digging yet. Trying to understand how it should work first.

No. .pipe() historically automatically unpiped from the source if the destination ended, i.e. the source is not paused while it should be.

I'm not sure i entirely agree with this. .pipe() will unpipe on 'end', however 'end' is emitted sometime after the destination has been .end():ed so there is still a possibility (which is quite probable) that pipe will call .write() after .end() but before 'end'.

I suspect we would need to update .pipe() to check for writableEnded before .write() to correctly achieve the behavior you are assuming.

@mcollina
Copy link
Member

mcollina commented Nov 3, 2020

let's get the fix in and then do a follow-up refactor.

@Trott Trott closed this as completed in 5a3f43b Nov 4, 2020
targos pushed a commit that referenced this issue Nov 4, 2020
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Add unit test for #35926

Refs: #35926

PR-URL: #35941
Fixes: #35926
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
mmomtchev added a commit to mmomtchev/node that referenced this issue Nov 22, 2020
Backport
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Refs: nodejs#35941
Fixes: nodejs#35926
enov pushed a commit to enov/node that referenced this issue Dec 4, 2020
Backport
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Refs: nodejs#35941
Fixes: nodejs#35926
BethGriggs pushed a commit that referenced this issue Dec 9, 2020
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Add unit test for #35926

Refs: #35926

Backport-PR-URL: #36375
PR-URL: #35941
Fixes: #35926
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
BethGriggs pushed a commit that referenced this issue Dec 10, 2020
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Add unit test for #35926

Refs: #35926

Backport-PR-URL: #36375
PR-URL: #35941
Fixes: #35926
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
BethGriggs pushed a commit that referenced this issue Dec 15, 2020
Decide the return status of writeOrBuffer before
calling stream.write which can reset state.length

Add unit test for #35926

Refs: #35926

Backport-PR-URL: #36375
PR-URL: #35941
Fixes: #35926
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Rich Trott <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug Issues with confirmed bugs. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants