Skip to content

Conversation

@addaleax
Copy link
Member

Alternative to #18673 that addresses the problem on the HTTP/2 level rather than the streams level itself. The test is taken from @XadillaX, whom I’d be very thankful if he could take a look at this :)

Refs: #18673
Fixes: #18169
Refs: https://github.com/nodejs/node/blob/v9.5.0/src/node_http2.cc#L1481-L1484
Refs: https://github.com/nodejs/node/blob/v9.5.0/lib/_http_outgoing.js#L659-L661

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

@nodejs-github-botnodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. dont-land-on-v4.x http2 Issues or PRs related to the http2 subsystem. labels Feb 22, 2018
@addaleaxaddaleaxforce-pushed the http2-fix-endless-loop branch from 27baa0a to b702ba3CompareFebruary 22, 2018 02:52
@apapirovski
Copy link
Contributor

Is there a way to standardize the behaviour between the various StreamBase implementations? As far as I can tell, the only place where we truly need these empty writes is TLSSocket#renegotiate...

(One side-effect of having a unique implementation of this logic for each StreamBase implementation is that http, for example, doesn't actually call the user-provided callback in the case of an empty write. That actually seems like a bug...)

@addaleax
Copy link
MemberAuthor

@apapirovski I think the fact that TLS uses them makes “empty writes flush the underlying protocol” part of the StreamBase API, and that’s a meaningful thing to do in the context of HTTP/2.

I’d be open to changing that. In reality, TLS should probably work more like HTTP/2 and flush state automatically after making changes to the protocol state, like what we do with Http2Scope right now.

That actually seems like a bug

Yeah, but it’s part of the write() method in _http_outgoing.js – it’s not related to our native streams impl, is it? (I also thought somebody had opened a PR for that. But I can’t find it, so I guess I’m wrong?)

@apapirovski
Copy link
Contributor

Yeah, but it’s part of the write() method in _http_outgoing.js – it’s not related to our native streams impl, is it? (I also thought somebody had opened a PR for that. But I can’t find it, so I guess I’m wrong?)

It's not, just commenting that the way it works is kind of problematic. We probably can't do much about it now but the http implementation makes a lot of non-obvious state assumptions. Like it's not at all clear that doing an empty write won't send the headers or trigger any of the follow-up logic that a non-empty write triggers.

I’d be open to changing that. In reality, TLS should probably work more like HTTP/2 and flush state automatically after making changes to the protocol state, like what we do with Http2Scope right now.

Yeah, that would be nice. Anyway, it's a bit hard for me to find time to think about much of this right now but will revisit when I have a bit more time.


In relation to this PR, I don't know how I feel about it vs the earlier one. There seem to be trade-offs with both.

// This is done here so that .write('', cb) is still a meaningful way to
// find out when the HTTP2 stream wants to consume data, and because the
// StreamBase API allows empty input chunks.
while (!stream->queue_.empty() && stream->queue_.front().buf.len == 0){
Copy link
Contributor

Choose a reason for hiding this comment

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

One question, if we remove the empty buffer and do nothing, will the header be sent?

Refs: https://github.com/nodejs/node/pull/18673/files#diff-696b2cc418addca5f3fe5020058f8b15R1622

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

@XadillaX Hm – I’m not sure I can wrap my head around everything, but this code here is only ever called by nghttp2 after the headers were sent anyway… does that answer your question?

So, yes, writing an empty buffer would trigger the headers to be sent, as I understand it.

@BridgeAR
Copy link
Member

@BridgeARBridgeAR added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Mar 2, 2018
@addaleax
Copy link
MemberAuthor

Landed in 9bc333c, and the test from @XadillaX in 16facd7.

Thanks for the reviews!

@addaleaxaddaleax closed this Mar 2, 2018
@addaleaxaddaleax removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Mar 2, 2018
@addaleaxaddaleax deleted the http2-fix-endless-loop branch March 2, 2018 11:50
@MylesBorinsMylesBorins mentioned this pull request Mar 6, 2018
@MylesBorinsMylesBorins mentioned this pull request May 2, 2018
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c++Issues and PRs that require attention from people who are familiar with C++.http2Issues or PRs related to the http2 subsystem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@addaleax@apapirovski@BridgeAR@jasnell@XadillaX@nodejs-github-bot