OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
15 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
16 #include "base/synchronization/waitable_event.h" | 16 #include "base/synchronization/waitable_event.h" |
17 #include "base/test/test_io_thread.h" | 17 #include "base/test/test_io_thread.h" |
18 #include "base/test/trace_event_analyzer.h" | 18 #include "base/test/trace_event_analyzer.h" |
19 #include "base/thread_task_runner_handle.h" | 19 #include "base/thread_task_runner_handle.h" |
| 20 #include "base/threading/platform_thread.h" |
20 #include "base/threading/thread.h" | 21 #include "base/threading/thread.h" |
21 #include "base/trace_event/memory_dump_provider.h" | 22 #include "base/trace_event/memory_dump_provider.h" |
22 #include "base/trace_event/process_memory_dump.h" | 23 #include "base/trace_event/process_memory_dump.h" |
23 #include "base/trace_event/trace_buffer.h" | 24 #include "base/trace_event/trace_buffer.h" |
24 #include "base/trace_event/trace_config_memory_test_util.h" | 25 #include "base/trace_event/trace_config_memory_test_util.h" |
25 #include "testing/gmock/include/gmock/gmock.h" | 26 #include "testing/gmock/include/gmock/gmock.h" |
26 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
27 | 28 |
28 using testing::_; | 29 using testing::_; |
29 using testing::AnyNumber; | 30 using testing::AnyNumber; |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 const MemoryDumpCallback& callback)); | 87 const MemoryDumpCallback& callback)); |
87 | 88 |
88 uint64_t GetTracingProcessId() const override { | 89 uint64_t GetTracingProcessId() const override { |
89 NOTREACHED(); | 90 NOTREACHED(); |
90 return MemoryDumpManager::kInvalidTracingProcessId; | 91 return MemoryDumpManager::kInvalidTracingProcessId; |
91 } | 92 } |
92 }; | 93 }; |
93 | 94 |
94 class MockMemoryDumpProvider : public MemoryDumpProvider { | 95 class MockMemoryDumpProvider : public MemoryDumpProvider { |
95 public: | 96 public: |
| 97 MOCK_METHOD0(Destructor, void()); |
96 MOCK_METHOD2(OnMemoryDump, | 98 MOCK_METHOD2(OnMemoryDump, |
97 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); | 99 bool(const MemoryDumpArgs& args, ProcessMemoryDump* pmd)); |
| 100 |
| 101 MockMemoryDumpProvider() : enable_mock_destructor(false) {} |
| 102 ~MockMemoryDumpProvider() override { |
| 103 if (enable_mock_destructor) |
| 104 Destructor(); |
| 105 } |
| 106 |
| 107 bool enable_mock_destructor; |
98 }; | 108 }; |
99 | 109 |
100 class MemoryDumpManagerTest : public testing::Test { | 110 class MemoryDumpManagerTest : public testing::Test { |
101 public: | 111 public: |
102 MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {} | 112 MemoryDumpManagerTest() : testing::Test(), kDefaultOptions() {} |
103 | 113 |
104 void SetUp() override { | 114 void SetUp() override { |
105 last_callback_success_ = false; | 115 last_callback_success_ = false; |
106 message_loop_.reset(new MessageLoop()); | 116 message_loop_.reset(new MessageLoop()); |
107 mdm_.reset(new MemoryDumpManager()); | 117 mdm_.reset(new MemoryDumpManager()); |
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 // Register a bound dump provider. | 788 // Register a bound dump provider. |
779 scoped_ptr<Thread> mdp_thread(new Thread("test thread")); | 789 scoped_ptr<Thread> mdp_thread(new Thread("test thread")); |
780 mdp_thread->Start(); | 790 mdp_thread->Start(); |
781 MockMemoryDumpProvider mdp_with_affinity; | 791 MockMemoryDumpProvider mdp_with_affinity; |
782 RegisterDumpProvider(&mdp_with_affinity, mdp_thread->task_runner(), | 792 RegisterDumpProvider(&mdp_with_affinity, mdp_thread->task_runner(), |
783 kDefaultOptions); | 793 kDefaultOptions); |
784 | 794 |
785 // Register also an unbound dump provider. Unbound dump providers are always | 795 // Register also an unbound dump provider. Unbound dump providers are always |
786 // invoked after bound ones. | 796 // invoked after bound ones. |
787 MockMemoryDumpProvider unbound_mdp; | 797 MockMemoryDumpProvider unbound_mdp; |
788 RegisterDumpProvider(&unbound_mdp); | 798 RegisterDumpProvider(&unbound_mdp, nullptr, kDefaultOptions); |
789 | 799 |
790 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); | 800 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
791 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); | 801 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(1); |
792 EXPECT_CALL(mdp_with_affinity, OnMemoryDump(_, _)) | 802 EXPECT_CALL(mdp_with_affinity, OnMemoryDump(_, _)) |
793 .Times(1) | 803 .Times(1) |
794 .WillOnce( | 804 .WillOnce( |
795 Invoke([&tracing_disabled_event](const MemoryDumpArgs&, | 805 Invoke([&tracing_disabled_event](const MemoryDumpArgs&, |
796 ProcessMemoryDump* pmd) -> bool { | 806 ProcessMemoryDump* pmd) -> bool { |
797 tracing_disabled_event.Wait(); | 807 tracing_disabled_event.Wait(); |
798 | 808 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 | 880 |
871 ASSERT_EQ(3u, events.size()); | 881 ASSERT_EQ(3u, events.size()); |
872 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); | 882 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(123))); |
873 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); | 883 ASSERT_EQ(1u, trace_analyzer::CountMatches(events, Query::EventPidIs(456))); |
874 ASSERT_EQ(1u, trace_analyzer::CountMatches( | 884 ASSERT_EQ(1u, trace_analyzer::CountMatches( |
875 events, Query::EventPidIs(GetCurrentProcId()))); | 885 events, Query::EventPidIs(GetCurrentProcId()))); |
876 ASSERT_EQ(events[0]->id, events[1]->id); | 886 ASSERT_EQ(events[0]->id, events[1]->id); |
877 ASSERT_EQ(events[0]->id, events[2]->id); | 887 ASSERT_EQ(events[0]->id, events[2]->id); |
878 } | 888 } |
879 | 889 |
| 890 // Tests the basics of the UnregisterAndDeleteDumpProviderSoon(): the |
| 891 // unregistration should actually delete the providers and not leak them. |
| 892 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoon) { |
| 893 InitializeMemoryDumpManager(false /* is_coordinator */); |
| 894 static const int kNumProviders = 3; |
| 895 int dtor_count = 0; |
| 896 std::vector<scoped_ptr<MemoryDumpProvider>> mdps; |
| 897 for (int i = 0; i < kNumProviders; ++i) { |
| 898 scoped_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider); |
| 899 mdp->enable_mock_destructor = true; |
| 900 EXPECT_CALL(*mdp, Destructor()) |
| 901 .WillOnce(Invoke([&dtor_count]() { dtor_count++; })); |
| 902 RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions); |
| 903 mdps.push_back(std::move(mdp)); |
| 904 } |
| 905 |
| 906 while (!mdps.empty()) { |
| 907 mdm_->UnregisterAndDeleteDumpProviderSoon(std::move(mdps.back())); |
| 908 mdps.pop_back(); |
| 909 } |
| 910 |
| 911 ASSERT_EQ(kNumProviders, dtor_count); |
| 912 } |
| 913 |
| 914 // This test checks against races when unregistering an unbound dump provider |
| 915 // from another thread while dumping. It registers one MDP and, when |
| 916 // OnMemoryDump() is called, it invokes UnregisterAndDeleteDumpProviderSoon() |
| 917 // from another thread. The OnMemoryDump() and the dtor call are expected to |
| 918 // happen on the same thread (the MemoryDumpManager utility thread). |
| 919 TEST_F(MemoryDumpManagerTest, UnregisterAndDeleteDumpProviderSoonDuringDump) { |
| 920 InitializeMemoryDumpManager(false /* is_coordinator */); |
| 921 scoped_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider); |
| 922 mdp->enable_mock_destructor = true; |
| 923 RegisterDumpProvider(mdp.get(), nullptr, kDefaultOptions); |
| 924 |
| 925 base::PlatformThreadRef thread_ref; |
| 926 auto self_unregister_from_another_thread = [&mdp, &thread_ref]( |
| 927 const MemoryDumpArgs&, ProcessMemoryDump*) -> bool { |
| 928 thread_ref = PlatformThread::CurrentRef(); |
| 929 TestIOThread thread_for_unregistration(TestIOThread::kAutoStart); |
| 930 thread_for_unregistration.PostTaskAndWait( |
| 931 FROM_HERE, |
| 932 base::Bind( |
| 933 &MemoryDumpManager::UnregisterAndDeleteDumpProviderSoon, |
| 934 base::Unretained(MemoryDumpManager::GetInstance()), |
| 935 base::Passed(scoped_ptr<MemoryDumpProvider>(std::move(mdp))))); |
| 936 thread_for_unregistration.Stop(); |
| 937 return true; |
| 938 }; |
| 939 EXPECT_CALL(*mdp, OnMemoryDump(_, _)) |
| 940 .Times(1) |
| 941 .WillOnce(Invoke(self_unregister_from_another_thread)); |
| 942 EXPECT_CALL(*mdp, Destructor()) |
| 943 .Times(1) |
| 944 .WillOnce(Invoke([&thread_ref]() { |
| 945 EXPECT_EQ(thread_ref, PlatformThread::CurrentRef()); |
| 946 })); |
| 947 |
| 948 EnableTracingWithLegacyCategories(MemoryDumpManager::kTraceCategory); |
| 949 EXPECT_CALL(*delegate_, RequestGlobalMemoryDump(_, _)).Times(2); |
| 950 for (int i = 0; i < 2; ++i) { |
| 951 RequestGlobalDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED, |
| 952 MemoryDumpLevelOfDetail::DETAILED); |
| 953 } |
| 954 DisableTracing(); |
| 955 } |
| 956 |
880 } // namespace trace_event | 957 } // namespace trace_event |
881 } // namespace base | 958 } // namespace base |
OLD | NEW |