Enterprise policy: Ignore the deprecated ForceSafeSearch if ForceGoogleSafeSearch...
[chromium-blink-merge.git] / base / trace_event / memory_dump_manager.cc
blob2c4b18e1dd74c9232262c7e94e1ccf8808b5be89
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
3 // found in the LICENSE file.
5 #include "base/trace_event/memory_dump_manager.h"
7 #include <algorithm>
9 #include "base/atomic_sequence_num.h"
10 #include "base/compiler_specific.h"
11 #include "base/trace_event/memory_dump_provider.h"
12 #include "base/trace_event/process_memory_dump.h"
13 #include "base/trace_event/trace_event_argument.h"
15 namespace base {
16 namespace trace_event {
18 namespace {
20 MemoryDumpManager* g_instance_for_testing = nullptr;
21 const int kTraceEventNumArgs = 1;
22 const char* kTraceEventArgNames[] = {"dumps"};
23 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
24 StaticAtomicSequenceNumber g_next_guid;
26 const char* MemoryDumpTypeToString(const MemoryDumpType& dump_type) {
27 switch (dump_type) {
28 case MemoryDumpType::TASK_BEGIN:
29 return "TASK_BEGIN";
30 case MemoryDumpType::TASK_END:
31 return "TASK_END";
32 case MemoryDumpType::PERIODIC_INTERVAL:
33 return "PERIODIC_INTERVAL";
34 case MemoryDumpType::EXPLICITLY_TRIGGERED:
35 return "EXPLICITLY_TRIGGERED";
37 NOTREACHED();
38 return "UNKNOWN";
41 } // namespace
43 // TODO(primiano): this should be smarter and should do something similar to
44 // trace event synthetic delays.
45 const char MemoryDumpManager::kTraceCategory[] =
46 TRACE_DISABLED_BY_DEFAULT("memory-dumps");
48 // static
49 MemoryDumpManager* MemoryDumpManager::GetInstance() {
50 if (g_instance_for_testing)
51 return g_instance_for_testing;
53 return Singleton<MemoryDumpManager,
54 LeakySingletonTraits<MemoryDumpManager>>::get();
57 // static
58 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
59 g_instance_for_testing = instance;
62 MemoryDumpManager::MemoryDumpManager()
63 : dump_provider_currently_active_(nullptr),
64 delegate_(nullptr),
65 memory_tracing_enabled_(0) {
66 g_next_guid.GetNext(); // Make sure that first guid is not zero.
69 MemoryDumpManager::~MemoryDumpManager() {
70 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
73 void MemoryDumpManager::Initialize() {
74 TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
75 trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
78 void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
79 AutoLock lock(lock_);
80 DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
81 delegate_ = delegate;
84 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
85 AutoLock lock(lock_);
86 if (std::find(dump_providers_registered_.begin(),
87 dump_providers_registered_.end(),
88 mdp) != dump_providers_registered_.end()) {
89 return;
91 dump_providers_registered_.push_back(mdp);
94 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
95 AutoLock lock(lock_);
97 // Remove from the registered providers list.
98 auto it = std::find(dump_providers_registered_.begin(),
99 dump_providers_registered_.end(), mdp);
100 if (it != dump_providers_registered_.end())
101 dump_providers_registered_.erase(it);
103 // Remove from the enabled providers list. This is to deal with the case that
104 // UnregisterDumpProvider is called while the trace is enabled.
105 it = std::find(dump_providers_enabled_.begin(), dump_providers_enabled_.end(),
106 mdp);
107 if (it != dump_providers_enabled_.end())
108 dump_providers_enabled_.erase(it);
111 void MemoryDumpManager::RequestGlobalDump(
112 MemoryDumpType dump_type,
113 const MemoryDumpCallback& callback) {
114 // Bail out immediately if tracing is not enabled at all.
115 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
116 return;
118 const uint64 guid =
119 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
121 // The delegate_ is supposed to be thread safe, immutable and long lived.
122 // No need to keep the lock after we ensure that a delegate has been set.
123 MemoryDumpManagerDelegate* delegate;
125 AutoLock lock(lock_);
126 delegate = delegate_;
129 if (delegate) {
130 // The delegate is in charge to coordinate the request among all the
131 // processes and call the CreateLocalDumpPoint on the local process.
132 MemoryDumpRequestArgs args = {guid, dump_type};
133 delegate->RequestGlobalMemoryDump(args, callback);
134 } else if (!callback.is_null()) {
135 callback.Run(guid, false /* success */);
139 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) {
140 RequestGlobalDump(dump_type, MemoryDumpCallback());
143 // Creates a memory dump for the current process and appends it to the trace.
144 void MemoryDumpManager::CreateProcessDump(
145 const MemoryDumpRequestArgs& args) {
146 bool did_any_provider_dump = false;
147 scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump());
149 // Serialize dump generation so that memory dump providers don't have to deal
150 // with thread safety.
152 AutoLock lock(lock_);
153 for (auto it = dump_providers_enabled_.begin();
154 it != dump_providers_enabled_.end();) {
155 dump_provider_currently_active_ = *it;
156 if (dump_provider_currently_active_->DumpInto(pmd.get())) {
157 did_any_provider_dump = true;
158 ++it;
159 } else {
160 LOG(ERROR) << "The memory dumper "
161 << dump_provider_currently_active_->GetFriendlyName()
162 << " failed, possibly due to sandboxing (crbug.com/461788), "
163 "disabling it for current process. Try restarting chrome "
164 "with the --no-sandbox switch.";
165 it = dump_providers_enabled_.erase(it);
167 dump_provider_currently_active_ = nullptr;
171 // Don't create a memory dump if all the dumpers failed.
172 if (!did_any_provider_dump)
173 return;
175 scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
176 pmd->AsValueInto(static_cast<TracedValue*>(event_value.get()));
177 const char* const event_name = MemoryDumpTypeToString(args.dump_type);
179 TRACE_EVENT_API_ADD_TRACE_EVENT(
180 TRACE_EVENT_PHASE_MEMORY_DUMP,
181 TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name,
182 args.dump_guid, kTraceEventNumArgs, kTraceEventArgNames,
183 kTraceEventArgTypes, nullptr /* arg_values */, &event_value,
184 TRACE_EVENT_FLAG_HAS_ID);
187 void MemoryDumpManager::OnTraceLogEnabled() {
188 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
189 // to figure out (and cache) which dumpers should be enabled or not.
190 // For the moment piggy back everything on the generic "memory" category.
191 bool enabled;
192 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
194 AutoLock lock(lock_);
195 if (enabled) {
196 dump_providers_enabled_.assign(dump_providers_registered_.begin(),
197 dump_providers_registered_.end());
198 } else {
199 dump_providers_enabled_.clear();
201 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
204 void MemoryDumpManager::OnTraceLogDisabled() {
205 AutoLock lock(lock_);
206 dump_providers_enabled_.clear();
207 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
210 } // namespace trace_event
211 } // namespace base