Closed
Bug 1228822
Opened 9 years ago
Closed 9 years ago
HTTP/2 pushed resource > 128KiB hangs indefinitely
Categories
(Core :: Networking: HTTP, defect)
Tracking
()
RESOLVED
FIXED
mozilla46
Tracking | Status | |
---|---|---|
firefox46 | --- | fixed |
People
(Reporter: tatsuhiro.t, Assigned: u408661)
References
Details
(Whiteboard: [spdy])
Attachments
(1 file, 1 obsolete file)
6.43 KB,
patch
|
mcmanus
:
review+
|
Details | Diff | Splinter Review |
User Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0 Build ID: 20151029151421 Steps to reproduce: 1. Configure web server to push resource of length more than 128KiB. 2. Browse the page where server pushes resource we configured in step 1. Actual results: Page does not load. Server could not send data because stream window is exhausted. Firefox's initial stream level window size is 128KiB (131072 bytes). But it does not send any WINDOW_UPDATE for that stream. When server pushed resource of length more than 128KiB, it stalls because there is no window left. I tested changing resource file size. * 128KiB - 1: OK * 128KiB: OK * 128KiB + 1: Fail Expected results: Page should be loaded. Firefox should send WINDOW_UPDATE to the pushed stream.
Updated•9 years ago
|
Comment 1•9 years ago
|
||
firefox will not accept more than 128KB of push until it sees a reason to pull (i.e use) the resource. At that point it will open up the window and continue the transfer.
Status: UNCONFIRMED → RESOLVED
Closed: 9 years ago
Resolution: --- → WONTFIX
Reporter | ||
Comment 2•9 years ago
|
||
I forget to tell you the important condition to cause this issue. This issue happens when I add 100ms latency using tc command. Without latency, firefox sends WINDOW_UPDATE to pushed streams, after received some bytes, which backs up your explanation. For some reason, if there is some latency, no WINDOW_UPDATE is sent. Very strange.
Comment 3•9 years ago
|
||
does firefox instead pull the stream? (there has to be a use of that uri somewhere, right?)
Reporter | ||
Comment 4•9 years ago
|
||
No, it doesn't. From HTTP log, firefox recognized pushed resource was really linked from HTML (Pushed Stream Match located id=0x2 key=https://nghttp2.org/[http2.2]/bug1228822/assets/css/bootstrap.css), and continued to read, and no download request was issued from firefox. But somehow firefox did not emit WINDOW_UPDATE to pushed resource, and stream was stalled because there was no window left. Again, page was not rendered at all. Spinner kept spinning. I setup test site to reproduce this issue: https://nghttp2.org/bug1228822/ Please add at least 100ms latency to reproduce this bug.
Comment 5•9 years ago
|
||
thanks tatsuhiro - nick, want to take a crack? also, tatsuhiro - was firefox using e10s?
Status: RESOLVED → REOPENED
Ever confirmed: true
Resolution: WONTFIX → ---
Updated•9 years ago
|
Assignee: nobody → hurley
Reporter | ||
Comment 6•9 years ago
|
||
"Enable multi-process Nightly" was disabled.
Here we go. We weren't updating pushed stream h2 state properly (it was always RESERVED_BY_REMOTE). The state we were stuck in does not allow WINDOW_UPDATE frames to be sent, so we never sent one. Oops :)
Attachment #8696110 -
Flags: review?(mcmanus)
xpcshell tests passed locally, but for the sake of sanity: https://treeherder.mozilla.org/#/jobs?repo=try&revision=a083ae7a7c40
Comment 9•9 years ago
|
||
the pushed stream should leave RESERVED_BY_REMOTE (changing to OPEN) when the response headers are read (when setallheadersreceived() is called on the push stream). so it appears that the source/sink matchup that calls adjustinitialwindow() is happening between PP (as PP is necessary to get into the matching table) and HEADERS - in which case it will return early because RESERVED_BY_REMOTE is the right state. There is a bug here - the window won't get bumped up from the push value to the pull value when this thing eventually goes to OPEN because you only get 1 crack at adjustinitialwindow. we should fix that. However, there is still a 128KB window (I would think) because we haven't seen any data frames yet (they might have been sent - but not recvd, because we know we haven't seen HEADERS yet because we are in RESERVED_BY_REMOTE).. as those DATA frames do come in we should send ACK^H^H^HWINDOW_UPDATE for some fraction of them in the usual way which would keep the stream flowing albeit perhaps at a suboptimal rate. And the bug reported is a total stall. What do you think is going on? Is it as simple as a bug in SetAllHeadersRecevied()? maybe start by seeing what the localwindow is when you see reserved_by_remote? I would think we could actually assert that it is 128KB in that state as HEADERS data is (famously) not flow controlled.
Updated•9 years ago
|
Attachment #8696110 -
Flags: review?(mcmanus) → review-
Assignee | ||
Comment 10•9 years ago
|
||
OK, so here's where we are (I discussed this with Pat just now in Orlando) - we actually *do* create a window bump... and then never send it over the wire, because we never flush our ourput. Oops! (I was looking too early in the log last time, the effect of the new coming patch is the same, but we send the bump at a more appropriate time.) Tests pass locally, running through try: https://treeherder.mozilla.org/#/jobs?repo=try&revision=a893d5f0b9be
Assignee | ||
Comment 11•9 years ago
|
||
OK, here's a new version, that properly sends out the window bump as discussed in person. I'm not totally happy with the state fudging here, but with Orlando-brain, I'm finding it difficult to come up with anything better at this moment. At least I can get validation (or not) of the appropriateness of this tactic. https://treeherder.mozilla.org/#/jobs?repo=try&revision=79dc16430e2b
Attachment #8697331 -
Flags: review?(mcmanus)
Attachment #8696110 -
Attachment is obsolete: true
Comment 12•9 years ago
|
||
Comment on attachment 8697331 [details] [diff] [review] patch Review of attachment 8697331 [details] [diff] [review]: ----------------------------------------------------------------- r+ with comment addressed ::: netwerk/protocol/http/Http2Stream.cpp @@ +1394,5 @@ > + if (NS_SUCCEEDED(rv)) { > + mSentPushWindowBump = true; > + } > + } else { > + MOZ_ASSERT(false, "Http2Stream::OnReadSegment unexpected state"); it seems like the point of the mSentPushWindowBump flag is to prevent doing this multiple times.. in which case you probably don't want the assert if it is called multiple times, right? if you do want the assert.. then I would restructure the block - instead of if (foo) { blah; } else { assert (false) } do it as assert (foo) blah;
Attachment #8697331 -
Flags: review?(mcmanus) → review+
Comment 14•9 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/3ed33231ee3c
Status: REOPENED → RESOLVED
Closed: 9 years ago → 9 years ago
status-firefox46:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → mozilla46
Comment 15•8 years ago
|
||
https://nghttp2.org/bug1228822/ is still broken for me.. which matches a bug report I've got in email about http2.undertow.io
Comment 16•8 years ago
|
||
I think I've got this worked out.. but I'm blocked on uploading it because the test tickles another smaller bug (which I think I can workaround in the test I will attach to this bug while fixing it separately.)
You need to log in
before you can comment on or make changes to this bug.
Description
•