diff options
author | bnc <bnc@chromium.org> | 2015-09-14 14:39:32 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-14 21:40:23 +0000 |
commit | 125cde33c45c37472639c94e4af73760042bdcb0 (patch) | |
tree | 6d963aa25b3e5843b2bd2eff44e2fc364a91b482 /net | |
parent | 4de274b2dff06c0ebce8c2738808f62e99f2b3ed (diff) | |
download | chromium_src-125cde33c45c37472639c94e4af73760042bdcb0.zip chromium_src-125cde33c45c37472639c94e4af73760042bdcb0.tar.gz chromium_src-125cde33c45c37472639c94e4af73760042bdcb0.tar.bz2 |
Do not drop data on the floor in SpdySession::DoReadLoop.
Patch Set 1 adds regression test, watch it specatularily fail in trybot logs.
Patch Set 2 fixes the issue.
BUG=531570
Review URL: https://codereview.chromium.org/1345453005
Cr-Commit-Position: refs/heads/master@{#348726}
Diffstat (limited to 'net')
-rw-r--r-- | net/spdy/spdy_session.cc | 6 | ||||
-rw-r--r-- | net/spdy/spdy_session_unittest.cc | 65 |
2 files changed, 68 insertions, 3 deletions
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc index 0233639..51c5714 100644 --- a/net/spdy/spdy_session.cc +++ b/net/spdy/spdy_session.cc @@ -1398,9 +1398,9 @@ int SpdySession::DoReadLoop(ReadState expected_read_state, int result) { if (result == ERR_IO_PENDING) break; - if (bytes_read_without_yielding > kYieldAfterBytesRead || - time_func_() > yield_after_time) { - read_state_ = READ_STATE_DO_READ; + if (read_state_ == READ_STATE_DO_READ && + (bytes_read_without_yielding > kYieldAfterBytesRead || + time_func_() > yield_after_time)) { base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::Bind(&SpdySession::PumpReadLoop, weak_factory_.GetWeakPtr(), diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc index c077195..738d4d7 100644 --- a/net/spdy/spdy_session_unittest.cc +++ b/net/spdy/spdy_session_unittest.cc @@ -2605,6 +2605,71 @@ TEST_P(SpdySessionTest, TestYieldingSlowReads) { EXPECT_TRUE(data.AllReadDataConsumed()); } +// Regression test for https://crbug.com/531570. +// Test the case where DoRead() takes long but returns synchronously. +TEST_P(SpdySessionTest, TestYieldingSlowSynchronousReads) { + session_deps_.host_resolver->set_synchronous_mode(true); + session_deps_.time_func = SlowReads; + + BufferedSpdyFramer framer(spdy_util_.spdy_version(), false); + + scoped_ptr<SpdyFrame> req1( + spdy_util_.ConstructSpdyGet(nullptr, 0, false, 1, MEDIUM, true)); + MockWrite writes[] = { + CreateMockWrite(*req1, 0), + }; + + scoped_ptr<SpdyFrame> partial_data_frame( + framer.CreateDataFrame(1, "foo ", 4, DATA_FLAG_NONE)); + scoped_ptr<SpdyFrame> finish_data_frame( + framer.CreateDataFrame(1, "bar", 3, DATA_FLAG_FIN)); + + scoped_ptr<SpdyFrame> resp1( + spdy_util_.ConstructSpdyGetSynReply(nullptr, 0, 1)); + + MockRead reads[] = { + CreateMockRead(*resp1, 1), MockRead(ASYNC, ERR_IO_PENDING, 2), + CreateMockRead(*partial_data_frame, 3, SYNCHRONOUS), + CreateMockRead(*partial_data_frame, 4, SYNCHRONOUS), + CreateMockRead(*partial_data_frame, 5, SYNCHRONOUS), + CreateMockRead(*finish_data_frame, 6, SYNCHRONOUS), + MockRead(ASYNC, 0, 7) // EOF + }; + + // Create SpdySession and SpdyStream and send the request. + SequencedSocketData data(reads, arraysize(reads), writes, arraysize(writes)); + session_deps_.socket_factory->AddSocketDataProvider(&data); + + CreateNetworkSession(); + CreateInsecureSpdySession(); + + base::WeakPtr<SpdyStream> spdy_stream1 = CreateStreamSynchronously( + SPDY_REQUEST_RESPONSE_STREAM, session_, test_url_, MEDIUM, BoundNetLog()); + ASSERT_TRUE(spdy_stream1.get() != nullptr); + EXPECT_EQ(0u, spdy_stream1->stream_id()); + test::StreamDelegateDoNothing delegate1(spdy_stream1); + spdy_stream1->SetDelegate(&delegate1); + + scoped_ptr<SpdyHeaderBlock> headers1( + spdy_util_.ConstructGetHeaderBlock(kDefaultURL)); + spdy_stream1->SendRequestHeaders(headers1.Pass(), NO_MORE_DATA_TO_SEND); + EXPECT_TRUE(spdy_stream1->HasUrlFromHeaders()); + + // Run until 1st read. + EXPECT_EQ(0u, delegate1.stream_id()); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(1u, delegate1.stream_id()); + + // Read all the data and verify SpdySession::DoReadLoop has posted a task. + data.CompleteRead(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ("foo foo foo bar", delegate1.TakeReceivedData()); + EXPECT_FALSE(spdy_stream1); + + EXPECT_TRUE(data.AllWriteDataConsumed()); + EXPECT_TRUE(data.AllReadDataConsumed()); +} + // Test that SpdySession::DoReadLoop yields while reading the // data. This test makes 32k + 1 bytes of data available on the socket // for reading. It then verifies that DoRead has yielded even though |