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

http2: fix compat stream read handling, add tests #15503

Closed

Conversation

apapirovski
Copy link
Member

@apapirovski apapirovski commented Sep 20, 2017

This PR is mostly about fixing #15491 but also includes some minor changes to improve overall reliability of the various stream events. Test cases for everything are included. (Some notes to follow directly in code.)

Thanks for reviewing!

cc @mcollina, @jasnell

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)

http2, test

@nodejs-github-bot nodejs-github-bot added the http2 Issues or PRs related to the http2 subsystem. label Sep 20, 2017
const onfinish = this[kFinish].bind(this);
stream.on('streamClosed', onfinish);
stream.on('finish', onfinish);
this.on('pause', onRequestPause);
this.on('resume', onRequestResume);
this.on('drain', onRequestDrain);
Copy link
Member Author

Choose a reason for hiding this comment

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

This isn't an event on Readable.

@@ -221,7 +222,7 @@ class Http2ServerRequest extends Readable {
_read(nread) {
const stream = this[kStream];
if (stream !== undefined) {
stream.resume();
process.nextTick(() => stream.resume());
Copy link
Member Author

@apapirovski apapirovski Sep 20, 2017

Choose a reason for hiding this comment

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

There's a race condition where pause can get evaluated in between resume being called and actually running (basically after resumeScheduled: true and before nextTick). This fixes it and passes all our tests (plus a new one that failed before).

Copy link
Member

Choose a reason for hiding this comment

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

we should not create a closure here, but rather use a top level function and pass the stream in there.

function onStreamClosedRequest() {
this[kRequest].push(null);
}

// TODO Http2Stream does not emit 'close'
Copy link
Member Author

Choose a reason for hiding this comment

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

I can remove these comments but I wanted it clear that these two don't run as things are. It's a bit confusing otherwise.

Copy link
Member

Choose a reason for hiding this comment

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

@jasnell can we remove those then? Or do you prefer if we add 'close' to Http2Stream?

Copy link
Member

Choose a reason for hiding this comment

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

I'm good with removing the comments.

Copy link
Member

Choose a reason for hiding this comment

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

oh lol... heh Matteo pointed out that I didn't understand the comments :-) This is true, I missed that.

I'm thinking we need to refactor this so that streamClosed and close are one and the same and that close is emitted appropriately. The one bit we'd have to account for is the code that is reported in streamClosed

Copy link
Member Author

@apapirovski apapirovski Sep 21, 2017

Choose a reason for hiding this comment

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

I could be wrong but I think @mcollina is asking about removing the functions which the comments refer to. If a 'close' event will be added to Http2Stream at some point then they should be kept but if that's not going to happen then we can safely remove. too slow lol

@apapirovski apapirovski force-pushed the patch-http2-compat-events branch from 4ae899a to 05de543 Compare September 20, 2017 21:27
if (this.writable) {
this.emit('close');
const response = this[kResponse];
if (response[kState].closed === false) {
Copy link
Member Author

Choose a reason for hiding this comment

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

writable is currently always true since Http2Stream doesn't emit a 'close' event but also this seems more correct, as far as I can reason about it and compare it to http1.

Copy link
Member

Choose a reason for hiding this comment

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

👍

@@ -158,13 +160,12 @@ class Http2ServerRequest extends Readable {
stream.on('end', onStreamEnd);
stream.on('error', onStreamError);
stream.on('close', onStreamClosedRequest);
stream.on('aborted', onStreamAbortedRequest.bind(this));
Copy link
Member Author

Choose a reason for hiding this comment

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

Any bind in here is expensive. I think only binding the most crucial things that are almost guaranteed to run (that being onfinish) is smart.

res.writable = false;
res.emit('finish');
const response = this[kResponse];
response.writable = false;
Copy link
Member

Choose a reason for hiding this comment

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

I would remove setting writable = false. This would break pump. See #15029

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.

Good work, a couple of nits.

@@ -221,7 +222,7 @@ class Http2ServerRequest extends Readable {
_read(nread) {
const stream = this[kStream];
if (stream !== undefined) {
stream.resume();
process.nextTick(() => stream.resume());
Copy link
Member

Choose a reason for hiding this comment

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

we should not create a closure here, but rather use a top level function and pass the stream in there.

Handle edge case where stream pause is called between resume being
called and actually evaluated. Other minor adjustments to avoid
various edge cases around stream events. Add new tests that cover
all changes.

Fixes: nodejs#15491
@apapirovski apapirovski force-pushed the patch-http2-compat-events branch from 05de543 to e1af8b9 Compare September 21, 2017 13:09
@apapirovski
Copy link
Member Author

Thanks for the review! Great spot re: the closure. All fixed now and ready for review/CI.

@mcollina
Copy link
Member

@apapirovski
Copy link
Member Author

apapirovski commented Sep 23, 2017

Sorry, just to confirm — anything I need to change or is this approved? Thanks! (Want to make sure this gets into 8.6.0 since without it people can't use HTTP2 compatibility layer very well, at least not for sending bigger amounts of data.)

Also, looks like CI was all good — failures are related to existing known issues reported elsewhere.

@mcollina
Copy link
Member

@apapirovski I understood @jasnell would like to have https://github.com/nodejs/node/pull/15503/files#r140291319 sorted before landing.

IMHO leaving around functions that are not called is not a good thing.

We can land this as it is right now, and send another PR to fix the 'streamClosed' problem, I'm ok with that as well.

@jasnell what do you think?

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

@apapirovski
Copy link
Member Author

apapirovski commented Sep 25, 2017

I mean, this PR didn't change that behaviour (it just documents it) and it fixes a legitimate, serious bug. Would be nice to get it into 8.6.0. I can't imagine we'll have a resolution for standardizing streamClosed and close before then.

(I'm happy to take a look at that next btw.)

@jasnell
Copy link
Member

jasnell commented Sep 25, 2017

I'm good with getting this landed now and included in 8.6.0, we can resolve the other issues separately

jasnell pushed a commit that referenced this pull request Sep 25, 2017
Handle edge case where stream pause is called between resume being
called and actually evaluated. Other minor adjustments to avoid
various edge cases around stream events. Add new tests that cover
all changes.

Fixes: #15491
PR-URL: #15503
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@jasnell
Copy link
Member

jasnell commented Sep 25, 2017

Landed in c705f10

@jasnell jasnell closed this Sep 25, 2017
@jasnell
Copy link
Member

jasnell commented Sep 25, 2017

cherry-picking into v8.x-staging next

jasnell pushed a commit that referenced this pull request Sep 25, 2017
Handle edge case where stream pause is called between resume being
called and actually evaluated. Other minor adjustments to avoid
various edge cases around stream events. Add new tests that cover
all changes.

Fixes: #15491
PR-URL: #15503
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@jasnell
Copy link
Member

jasnell commented Sep 25, 2017

Landed in v8.x-staging...

@apapirovski apapirovski deleted the patch-http2-compat-events branch September 25, 2017 20:44
MylesBorins pushed a commit that referenced this pull request Sep 29, 2017
Handle edge case where stream pause is called between resume being
called and actually evaluated. Other minor adjustments to avoid
various edge cases around stream events. Add new tests that cover
all changes.

Fixes: #15491
PR-URL: #15503
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
addaleax pushed a commit to addaleax/ayo that referenced this pull request Sep 30, 2017
Handle edge case where stream pause is called between resume being
called and actually evaluated. Other minor adjustments to avoid
various edge cases around stream events. Add new tests that cover
all changes.

Fixes: nodejs/node#15491
PR-URL: nodejs/node#15503
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: James M Snell <[email protected]>
@MylesBorins MylesBorins mentioned this pull request Oct 3, 2017
@apapirovski apapirovski mentioned this pull request May 16, 2018
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
http2 Issues or PRs related to the http2 subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants