QuicHttpStream reports ERR_QUIC_PROTOCOL_ERROR without details if trailer block is received |
||
Issue descriptionI've found this while debugging cronet_test for iOS, but I think it may apply to Chrome on all platforms. Steps used to reproduce: 1. Setup iOS Dev environment on Mac OS X. 2. Generate Cronet projects - components/cronet/tools/cr_cronet.py gn. 3. Build and run cronet test - components/cronet/tools/cr_cronet.py build-test 4. Change start_cronet.mm to disable HTTP cache: [Cronet setHttpCacheType:CRNHttpCacheTypeDisabled] 5. Build and run cronet test - components/cronet/tools/cr_cronet.py build-test 6. Observe HttpTest.NSURLSessionReceivesData test failing with error: [0413/103033.868882:ERROR:crn_http_protocol_handler.mm(762)] HttpProtocolHandlerCore - Network error: net::ERR_QUIC_PROTOCOL_ERROR (-356)QUIC Error Code = 0 7. [Optional] Spend few hours trying to figure out what's wrong with cache. 8. Change SetupQuicHttpResponseCache() in components/grpc_support/test/quic_test_server.cc to skip trailers from response. 9. Build and run cronet test - components/cronet/tools/cr_cronet.py build-test 10. Observe success! Couple of notes: - Enabling disk cache appears to mask the problem, probably because disk cache silently drops trailers. This makes me think that Chrome may be ok. - UrlRequest::PopulateNetErrorDetails doesn't provide any additional info in |quic_connection_error|, probably because it is not really a quic connection error.
,
Apr 13 2017
* thread #10: tid = 0x2403f0, 0x00000001127d3f42 Cronet`net::QuicHttpStream::ComputeResponseStatus(this=0x00007fa8bfc01e20) const + 786 at quic_http_stream.cc:895, name = 'Chrome Network IO Thread', stop reason = breakpoint 6.2
* frame #0: 0x00000001127d3f42 Cronet`net::QuicHttpStream::ComputeResponseStatus(this=0x00007fa8bfc01e20) const + 786 at quic_http_stream.cc:895
frame #1: 0x00000001127d0f4a Cronet`net::QuicHttpStream::SaveResponseStatus(this=0x00007fa8bfc01e20) + 42 at quic_http_stream.cc:852
frame #2: 0x00000001127d24ae Cronet`net::QuicHttpStream::OnClose(this=0x00007fa8bfc01e20) + 78 at quic_http_stream.cc:485
frame #3: 0x00000001127af776 Cronet`net::QuicChromiumClientStream::OnClose(this=0x00007fa8bfc005f0) + 54 at quic_chromium_client_stream.cc:108
frame #4: 0x000000011291747d Cronet`net::QuicSession::CloseStreamInner(this=0x00007fa8c6018a00, stream_id=5, locally_reset=false) + 2525 at quic_session.cc:390
frame #5: 0x0000000112895064 Cronet`net::QuicClientSessionBase::CloseStreamInner(this=0x00007fa8c6018a00, stream_id=5, locally_reset=false) + 52 at quic_client_session_base.cc:177
frame #6: 0x0000000112916854 Cronet`net::QuicSession::CloseStream(this=0x00007fa8c6018a00, stream_id=5) + 36 at quic_session.cc:339
frame #7: 0x000000011279c86a Cronet`net::QuicChromiumClientSession::CloseStream(this=0x00007fa8c6018a00, stream_id=5) + 202 at quic_chromium_client_session.cc:775
frame #8: 0x000000011294ccea Cronet`net::QuicStream::CloseReadSide(this=0x00007fa8bfc005f0) + 778 at quic_stream.cc:376
frame #9: 0x000000011294ce71 Cronet`net::QuicStream::OnFinRead(this=0x00007fa8bfc005f0) + 225 at quic_stream.cc:167
frame #10: 0x00000001127d17f2 Cronet`net::QuicHttpStream::OnHeadersAvailable(this=0x00007fa8bfc01e20, headers=0x00007000041acfb0, frame_len=50) + 114 at quic_http_stream.cc:450
frame #11: 0x00000001127b0c72 Cronet`net::QuicChromiumClientStream::NotifyDelegateOfHeadersComplete(this=0x00007fa8bfc005f0, headers=SpdyHeaderBlock @ 0x00007000041acfb0, frame_len=50) + 306 at quic_chromium_client_stream.cc:264
,
Jan 3
|
||
►
Sign in to add a comment |
||
Comment 1 by xunji...@chromium.org
, Apr 13 2017QuicHttpStream should ignore trailers. Where is this ERR_QUIC_PROTOCOL_ERROR coming from? void QuicHttpStream::OnHeadersAvailable(const SpdyHeaderBlock& headers, size_t frame_len) { headers_bytes_received_ += frame_len; // QuicHttpStream ignores trailers. if (response_headers_received_) { if (stream_->IsDoneReading()) { // Close the read side. If the write side has been closed, this will // invoke QuicHttpStream::OnClose to reset the stream. stream_->OnFinRead(); SetResponseStatus(OK); } return; } int rv = ProcessResponseHeaders(headers); if (rv != ERR_IO_PENDING && !callback_.is_null()) { DoCallback(rv); } }