Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(639)

Side by Side Diff: net/http/http_pipelined_network_transaction_unittest.cc

Issue 8820005: Fix race between OnPipelineFeedback and (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix Win build Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/http/http_pipelined_host_impl.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <string> 5 #include <string>
6 6
7 #include "base/memory/ref_counted.h" 7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_vector.h" 8 #include "base/memory/scoped_vector.h"
9 #include "base/stringprintf.h" 9 #include "base/stringprintf.h"
10 #include "base/utf_string_conversions.h" 10 #include "base/utf_string_conversions.h"
(...skipping 622 matching lines...) Expand 10 before | Expand all | Expand 10 after
633 data_vector_[0]->RunFor(3); 633 data_vector_[0]->RunFor(3);
634 EXPECT_EQ(OK, second_one_callback.WaitForResult()); 634 EXPECT_EQ(OK, second_one_callback.WaitForResult());
635 data_vector_[0]->StopAfter(100); 635 data_vector_[0]->StopAfter(100);
636 ExpectResponse("second-pipeline-one.html", second_one_transaction); 636 ExpectResponse("second-pipeline-one.html", second_one_transaction);
637 EXPECT_EQ(OK, second_two_callback.WaitForResult()); 637 EXPECT_EQ(OK, second_two_callback.WaitForResult());
638 ExpectResponse("second-pipeline-two.html", second_two_transaction); 638 ExpectResponse("second-pipeline-two.html", second_two_transaction);
639 639
640 ClientSocketPoolManager::set_max_sockets_per_group(old_max_sockets); 640 ClientSocketPoolManager::set_max_sockets_per_group(old_max_sockets);
641 } 641 }
642 642
643 class DataRunnerObserver : public MessageLoop::TaskObserver {
644 public:
645 DataRunnerObserver(DeterministicSocketData* data, int run_before_task)
646 : data_(data),
647 run_before_task_(run_before_task),
648 current_task_(0) { }
649
650 virtual void WillProcessTask(base::TimeTicks) OVERRIDE {
651 ++current_task_;
652 if (current_task_ == run_before_task_) {
653 data_->Run();
654 MessageLoop::current()->RemoveTaskObserver(this);
655 }
656 }
657
658 virtual void DidProcessTask(base::TimeTicks) OVERRIDE { }
659
660 private:
661 DeterministicSocketData* data_;
662 int run_before_task_;
663 int current_task_;
664 };
665
666 TEST_F(HttpPipelinedNetworkTransactionTest, OpenPipelinesWhileBinding) {
667 // There was a racy crash in the pipelining code. This test recreates that
668 // race. The steps are:
669 // 1. The first request starts a pipeline and requests headers.
670 // 2. HttpStreamFactoryImpl::Job tries to bind a pending request to a new
671 // pipeline and queues a task to do so.
672 // 3. Before that task runs, the first request receives its headers and
673 // determines this host is probably capable of pipelining.
674 // 4. All of the hosts' pipelines are notified they have capacity in a loop.
675 // 5. On the first iteration, the first pipeline is opened up to accept new
676 // requests and steals the request from step #2.
677 // 6. The pipeline from #2 is deleted because it has no streams.
678 // 7. On the second iteration, the host tries to notify the pipeline from step
679 // #2 that it has capacity. This is a use-after-free.
680 Initialize();
681
682 MockWrite writes[] = {
683 MockWrite(false, 0, "GET /one.html HTTP/1.1\r\n"
684 "Host: localhost\r\n"
685 "Connection: keep-alive\r\n\r\n"),
686 MockWrite(true, 3, "GET /two.html HTTP/1.1\r\n"
687 "Host: localhost\r\n"
688 "Connection: keep-alive\r\n\r\n"),
689 };
690 MockRead reads[] = {
691 MockRead(false, 1, "HTTP/1.1 200 OK\r\n"),
692 MockRead(true, 2, "Content-Length: 8\r\n\r\n"),
693 MockRead(false, 4, "one.html"),
694 MockRead(false, 5, "HTTP/1.1 200 OK\r\n"),
695 MockRead(false, 6, "Content-Length: 8\r\n\r\n"),
696 MockRead(false, 7, "two.html"),
697 };
698 AddExpectedConnection(reads, arraysize(reads), writes, arraysize(writes));
699
700 AddExpectedConnection(NULL, 0, NULL, 0);
701
702 HttpNetworkTransaction one_transaction(session_.get());
703 TestOldCompletionCallback one_callback;
704 EXPECT_EQ(ERR_IO_PENDING,
705 one_transaction.Start(GetRequestInfo("one.html"), &one_callback,
706 BoundNetLog()));
707
708 data_vector_[0]->SetStop(2);
709 data_vector_[0]->Run();
710
711 HttpNetworkTransaction two_transaction(session_.get());
712 TestOldCompletionCallback two_callback;
713 EXPECT_EQ(ERR_IO_PENDING,
714 two_transaction.Start(GetRequestInfo("two.html"), &two_callback,
715 BoundNetLog()));
716 // Posted tasks should be:
717 // 1. MockHostResolverBase::ResolveNow
718 // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1
719 // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2
720 //
721 // We need to make sure that the response that triggers OnPipelineFeedback(OK)
722 // is called in between when task #3 is scheduled and when it runs. The
723 // DataRunnerObserver does that.
724 DataRunnerObserver observer(data_vector_[0].get(), 3);
725 MessageLoop::current()->AddTaskObserver(&observer);
726 data_vector_[0]->SetStop(4);
727 MessageLoop::current()->RunAllPending();
728 data_vector_[0]->SetStop(10);
729
730 EXPECT_EQ(OK, one_callback.WaitForResult());
731 ExpectResponse("one.html", one_transaction);
732 EXPECT_EQ(OK, two_callback.WaitForResult());
733 ExpectResponse("two.html", two_transaction);
734 }
735
643 } // anonymous namespace 736 } // anonymous namespace
644 737
645 } // namespace net 738 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_pipelined_host_impl.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698