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: don't emit drain if ended #29086

Closed
wants to merge 1 commit into from

Conversation

ronag
Copy link
Member

@ronag ronag commented Aug 11, 2019

Don't emit 'drain' if the stream has been ended. 'drain' should only be emitted if the stream wants more data.

See, https://nodejs.org/api/stream.html#stream_event_drain.

the 'drain' event will be emitted when it is appropriate to resume writing data to the stream.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

NOTE TO SELF: After this is merged look into emitting 'drain' after state.length < hwm instead of state.length === 0.

@nodejs-github-bot nodejs-github-bot added the stream Issues and PRs related to the stream subsystem. label Aug 11, 2019
@ronag ronag force-pushed the stream-write-drain branch from 8503eb9 to a7d029b Compare August 11, 2019 15:51
@ronag ronag mentioned this pull request Aug 12, 2019
7 tasks
@Trott
Copy link
Member

Trott commented Aug 13, 2019

@nodejs/streams

@nodejs-github-bot
Copy link
Collaborator

@Trott
Copy link
Member

Trott commented Aug 16, 2019

Looks fine to me, but it would be good to have someone on @nodejs/streams vet it.

Doesn't seem to have semver implications to me but there may be something subtle I'm missing?

Doesn't seem like it would require benchmarking, but again, maybe I'm wrong?

@Trott Trott requested a review from mcollina August 16, 2019 23:21
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a good CITGM run

@mcollina
Copy link
Member

I’m good with this being a patch.

@Trott
Copy link
Member

Trott commented Aug 17, 2019

I’m good with this being a patch.

Do you still want a CITGM run? (I'm happy to do it if we want to be extra cautious, but also happy to skip it if it's not necessary.)

Copy link
Member

@Trott Trott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Making my previous tentative LGTM more official.

@mcollina
Copy link
Member

mcollina commented Aug 17, 2019 via email

@Trott
Copy link
Member

Trott commented Aug 17, 2019

CITGM (queued): https://ci.nodejs.org/job/citgm-smoker/1958/

@Trott Trott added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Aug 17, 2019
@Trott
Copy link
Member

Trott commented Aug 17, 2019

Those CITGM results seem OK to me after a quick review. You too @mcollina?

@Trott
Copy link
Member

Trott commented Aug 19, 2019

Extra-super-cautious second CITGM: https://ci.nodejs.org/job/citgm-smoker/1969/

@Trott
Copy link
Member

Trott commented Aug 20, 2019

Landed in 605d7c4

@Trott Trott closed this Aug 20, 2019
Trott pushed a commit that referenced this pull request Aug 20, 2019
PR-URL: #29086
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@isaacs
Copy link
Contributor

isaacs commented Aug 22, 2019

I was mistaken. bdf07f4 is the problem, not this commit. Original comment hidden in details.

This commit is causing problems. I think it should be reverted.

While the docs for 'drain' mention that it's appropriate to write more data, in practice throughout the ecosystem, 'drain' means "all the written data has been consumed", whether the stream is now ended or not.

As a result, .once('drain') handlers are not removed when they should be, and pipelines can even back up if they depend on this behavior. We're seeing this in npm, where users get a flood of "excess event handler" warnings.

Thanks for your attention.

@isaacs

This comment has been minimized.

@mcollina
Copy link
Member

Thanks, we’ll revert this asap.

@mcollina
Copy link
Member

@isaacs have you got a module that broke/had issue about this? I'd love to add a unit test or something to CITGM so we can avoid regressions.

@ronag
Copy link
Member Author

ronag commented Aug 22, 2019

Makes sense. Is there anything I can do here to follow up? Update the docs to reflect the actual behaviour?

Though I still think the behaviour of this PR is the correct one. Currently it is theoretically possible to cause an write after end in otherwise valid code. I guess we could work around that by updating the docs and also asking the user to check the .writable property after 'drain' and before write(). Not optimal, but maybe sufficient compromise? Or do we revert the revert in a semver-major?

@isaacs
Copy link
Contributor

isaacs commented Aug 22, 2019

@mcollina Run npm install against https://github.com/ljharb/es-abstract and you'll see a flood of warnings.

I don't have an example of it backup up a stream and causing problems that way. It'd be harder to reproduce in the wild, because it'd depend on some very specific behavior and timing, but could probably be synthetically created in a test.

@ronag
Copy link
Member Author

ronag commented Aug 22, 2019

Run npm install against https://github.com/ljharb/es-abstract and you'll see a flood of warnings.

Isn't that the same issue as #29239? i.e. something else?

@isaacs
Copy link
Contributor

isaacs commented Aug 22, 2019

@ronag It could be! The issue I saw is that drain isn't getting emitted when it should be, so it led me to this commit, and reverting seems to make the problem go away on my system. But it's possible that it's both, or neither, or something else :)

I'm not sure the best way to go about getting this done, but personally, I'd really like a more massive overhaul of the streams implementation if we're talking about semver major changes. The drain sematic is really not the worst problem.

We could improve performance and vastly simplify the codebase, with a minimal disruption to userland code, by moving to something like minipass. If streams were synchronous, and the class hierarchy rooted on a passthrough implementation (rather than squishing together Readable and Writable into Duplex), then the entire system would be much less brittle. I'm not sure the best way to go about proposing that these days, but I'd be happy to help however I can.

@ronag
Copy link
Member Author

ronag commented Aug 22, 2019

@isaacs: Could you try not reverting this commit and instead revert bdf07f4? I'm just curious whether that makes a difference for you.

@isaacs
Copy link
Contributor

isaacs commented Aug 22, 2019

@ronag Will do. I do still think this behavior change is a mistake in a minor version, so probably both need to be rolled back.

@isaacs
Copy link
Contributor

isaacs commented Aug 22, 2019

Confirmed @ronag's hunch. Reverting bdf07f4 (or both bdf07f4 and 605d7c4) makes the warnings go away, and reverting only 605d7c4 does not.

BridgeAR pushed a commit that referenced this pull request Sep 3, 2019
PR-URL: #29086
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@BridgeAR BridgeAR mentioned this pull request Sep 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. stream Issues and PRs related to the stream subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants