Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 MockWrite writes2[] = {}; | |
| 701 MockRead reads2[] = {}; | |
| 702 AddExpectedConnection(reads2, 0, writes2, 0); | |
| 703 | |
| 704 HttpNetworkTransaction one_transaction(session_.get()); | |
| 705 TestOldCompletionCallback one_callback; | |
| 706 EXPECT_EQ(ERR_IO_PENDING, | |
| 707 one_transaction.Start(GetRequestInfo("one.html"), &one_callback, | |
| 708 BoundNetLog())); | |
| 709 | |
| 710 data_vector_[0]->SetStop(2); | |
| 711 data_vector_[0]->Run(); | |
| 712 | |
| 713 HttpNetworkTransaction two_transaction(session_.get()); | |
| 714 TestOldCompletionCallback two_callback; | |
| 715 EXPECT_EQ(ERR_IO_PENDING, | |
| 716 two_transaction.Start(GetRequestInfo("two.html"), &two_callback, | |
| 717 BoundNetLog())); | |
| 718 // Posted tasks should be: | |
| 719 // 1. MockHostResolverBase::ResolveNow | |
| 720 // 2. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 1 | |
| 721 // 3. HttpStreamFactoryImpl::Job::OnStreamReadyCallback for job 2 | |
| 722 DataRunnerObserver observer(data_vector_[0].get(), 3); | |
|
mmenke
2011/12/06 15:29:03
Why is this needed, exactly?
James Simonsen
2011/12/06 19:41:35
Added a comment.
This was just the easiest way I
mmenke
2011/12/06 19:45:37
Ahh, right.
| |
| 723 MessageLoop::current()->AddTaskObserver(&observer); | |
| 724 data_vector_[0]->SetStop(4); | |
| 725 MessageLoop::current()->RunAllPending(); | |
| 726 data_vector_[0]->SetStop(10); | |
| 727 | |
| 728 EXPECT_EQ(OK, one_callback.WaitForResult()); | |
| 729 ExpectResponse("one.html", one_transaction); | |
| 730 EXPECT_EQ(OK, two_callback.WaitForResult()); | |
| 731 ExpectResponse("two.html", two_transaction); | |
| 732 } | |
| 733 | |
| 643 } // anonymous namespace | 734 } // anonymous namespace |
| 644 | 735 |
| 645 } // namespace net | 736 } // namespace net |
| OLD | NEW |