summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorbnc <bnc@chromium.org>2015-09-14 14:39:32 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-14 21:40:23 +0000
commit125cde33c45c37472639c94e4af73760042bdcb0 (patch)
tree6d963aa25b3e5843b2bd2eff44e2fc364a91b482 /net
parent4de274b2dff06c0ebce8c2738808f62e99f2b3ed (diff)
downloadchromium_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.cc6
-rw-r--r--net/spdy/spdy_session_unittest.cc65
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