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

Side by Side Diff: base/trace_event/memory_dump_manager.cc

Issue 1128733002: Update from https://crrev.com/328418 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 7 months 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
OLDNEW
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 <algorithm> 7 #include <algorithm>
8 8
9 #include "base/atomic_sequence_num.h" 9 #include "base/atomic_sequence_num.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/trace_event/memory_dump_provider.h" 11 #include "base/trace_event/memory_dump_provider.h"
12 #include "base/trace_event/memory_dump_session_state.h" 12 #include "base/trace_event/memory_dump_session_state.h"
13 #include "base/trace_event/process_memory_dump.h" 13 #include "base/trace_event/process_memory_dump.h"
14 #include "base/trace_event/trace_event_argument.h" 14 #include "base/trace_event/trace_event_argument.h"
15 #include "build/build_config.h"
16
17 #if !defined(OS_NACL)
18 #include "base/trace_event/process_memory_totals_dump_provider.h"
19 #endif
15 20
16 #if defined(OS_LINUX) || defined(OS_ANDROID) 21 #if defined(OS_LINUX) || defined(OS_ANDROID)
17 #include "base/trace_event/malloc_dump_provider.h" 22 #include "base/trace_event/malloc_dump_provider.h"
18 #include "base/trace_event/process_memory_maps_dump_provider.h" 23 #include "base/trace_event/process_memory_maps_dump_provider.h"
19 #include "base/trace_event/process_memory_totals_dump_provider.h" 24 #endif
20 #elif defined(OS_WIN) 25
26 #if defined(OS_ANDROID)
27 #include "base/trace_event/java_heap_dump_provider_android.h"
28 #endif
29
30 #if defined(OS_WIN)
21 #include "base/trace_event/winheap_dump_provider_win.h" 31 #include "base/trace_event/winheap_dump_provider_win.h"
22 #endif 32 #endif
23 33
24 namespace base { 34 namespace base {
25 namespace trace_event { 35 namespace trace_event {
26 36
27 namespace { 37 namespace {
28 38
29 // TODO(primiano): this should be smarter and should do something similar to 39 // TODO(primiano): this should be smarter and should do something similar to
30 // trace event synthetic delays. 40 // trace event synthetic delays.
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 147 }
138 148
139 // static 149 // static
140 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { 150 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
141 if (instance) 151 if (instance)
142 instance->skip_core_dumpers_auto_registration_for_testing_ = true; 152 instance->skip_core_dumpers_auto_registration_for_testing_ = true;
143 g_instance_for_testing = instance; 153 g_instance_for_testing = instance;
144 } 154 }
145 155
146 MemoryDumpManager::MemoryDumpManager() 156 MemoryDumpManager::MemoryDumpManager()
147 : dump_provider_currently_active_(nullptr), 157 : delegate_(nullptr),
148 delegate_(nullptr),
149 memory_tracing_enabled_(0), 158 memory_tracing_enabled_(0),
150 skip_core_dumpers_auto_registration_for_testing_(false) { 159 skip_core_dumpers_auto_registration_for_testing_(false) {
151 g_next_guid.GetNext(); // Make sure that first guid is not zero. 160 g_next_guid.GetNext(); // Make sure that first guid is not zero.
152 } 161 }
153 162
154 MemoryDumpManager::~MemoryDumpManager() { 163 MemoryDumpManager::~MemoryDumpManager() {
155 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this); 164 base::trace_event::TraceLog::GetInstance()->RemoveEnabledStateObserver(this);
156 } 165 }
157 166
158 void MemoryDumpManager::Initialize() { 167 void MemoryDumpManager::Initialize() {
159 TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list. 168 TRACE_EVENT0(kTraceCategory, "init"); // Add to trace-viewer category list.
160 trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this); 169 trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(this);
161 170
162 if (skip_core_dumpers_auto_registration_for_testing_) 171 if (skip_core_dumpers_auto_registration_for_testing_)
163 return; 172 return;
164 173
174 // Enable the core dump providers.
175 #if !defined(OS_NACL)
176 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
177 #endif
178
165 #if defined(OS_LINUX) || defined(OS_ANDROID) 179 #if defined(OS_LINUX) || defined(OS_ANDROID)
166 // Enable the core dump providers.
167 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
168 RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); 180 RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
169 RegisterDumpProvider(MallocDumpProvider::GetInstance()); 181 RegisterDumpProvider(MallocDumpProvider::GetInstance());
170 #elif defined(OS_WIN) 182 #endif
183
184 #if defined(OS_ANDROID)
185 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance());
186 #endif
187
188 #if defined(OS_WIN)
171 RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); 189 RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
172 #endif 190 #endif
173 } 191 }
174 192
175 void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) { 193 void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
176 AutoLock lock(lock_); 194 AutoLock lock(lock_);
177 DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_); 195 DCHECK_EQ(static_cast<MemoryDumpManagerDelegate*>(nullptr), delegate_);
178 delegate_ = delegate; 196 delegate_ = delegate;
179 } 197 }
180 198
199 void MemoryDumpManager::RegisterDumpProvider(
200 MemoryDumpProvider* mdp,
201 const scoped_refptr<SingleThreadTaskRunner>& task_runner) {
202 MemoryDumpProviderInfo mdp_info(task_runner);
203 AutoLock lock(lock_);
204 dump_providers_.insert(std::make_pair(mdp, mdp_info));
205 }
206
181 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) { 207 void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
182 AutoLock lock(lock_); 208 RegisterDumpProvider(mdp, nullptr);
183 dump_providers_registered_.insert(mdp);
184 } 209 }
185 210
186 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) { 211 void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
187 AutoLock lock(lock_); 212 AutoLock lock(lock_);
188 213
214 auto it = dump_providers_.find(mdp);
215 if (it == dump_providers_.end())
216 return;
217
218 const MemoryDumpProviderInfo& mdp_info = it->second;
189 // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe 219 // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
190 // only if the MDP has specified a thread affinity (via task_runner()) AND 220 // only if the MDP has specified a thread affinity (via task_runner()) AND
191 // the unregistration happens on the same thread (so the MDP cannot unregister 221 // the unregistration happens on the same thread (so the MDP cannot unregister
192 // and DumpInto() at the same time). 222 // and OnMemoryDump() at the same time).
193 // Otherwise, it is not possible to guarantee that its unregistration is 223 // Otherwise, it is not possible to guarantee that its unregistration is
194 // race-free. If you hit this DCHECK, your MDP has a bug. 224 // race-free. If you hit this DCHECK, your MDP has a bug.
195 DCHECK_IMPLIES( 225 DCHECK_IMPLIES(
196 subtle::NoBarrier_Load(&memory_tracing_enabled_), 226 subtle::NoBarrier_Load(&memory_tracing_enabled_),
197 mdp->task_runner() && mdp->task_runner()->BelongsToCurrentThread()) 227 mdp_info.task_runner && mdp_info.task_runner->BelongsToCurrentThread())
198 << "The MemoryDumpProvider " << mdp->GetFriendlyName() << " attempted to " 228 << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
199 << "unregister itself in a racy way. Please file a crbug."; 229 << " Please file a crbug.";
200 230
201 // Remove from the enabled providers list. This is to deal with the case that 231 // Remove from the enabled providers list. This is to deal with the case that
202 // UnregisterDumpProvider is called while the trace is enabled. 232 // UnregisterDumpProvider is called while the trace is enabled.
203 dump_providers_enabled_.erase(mdp); 233 dump_providers_.erase(it);
204 dump_providers_registered_.erase(mdp);
205 } 234 }
206 235
207 void MemoryDumpManager::RequestGlobalDump( 236 void MemoryDumpManager::RequestGlobalDump(
208 MemoryDumpType dump_type, 237 MemoryDumpType dump_type,
209 const MemoryDumpCallback& callback) { 238 const MemoryDumpCallback& callback) {
210 // Bail out immediately if tracing is not enabled at all. 239 // Bail out immediately if tracing is not enabled at all.
211 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) 240 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
212 return; 241 return;
213 242
214 const uint64 guid = 243 const uint64 guid =
(...skipping 22 matching lines...) Expand all
237 } 266 }
238 267
239 // Creates a memory dump for the current process and appends it to the trace. 268 // Creates a memory dump for the current process and appends it to the trace.
240 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, 269 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
241 const MemoryDumpCallback& callback) { 270 const MemoryDumpCallback& callback) {
242 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder( 271 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder(
243 new ProcessMemoryDumpHolder(args, session_state_, callback)); 272 new ProcessMemoryDumpHolder(args, session_state_, callback));
244 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; 273 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
245 bool did_any_provider_dump = false; 274 bool did_any_provider_dump = false;
246 275
247 // Iterate over the active dump providers and invoke DumpInto(pmd). 276 // Iterate over the active dump providers and invoke OnMemoryDump(pmd).
248 // The MDM guarantees linearity (at most one MDP is active within one 277 // The MDM guarantees linearity (at most one MDP is active within one
249 // process) and thread-safety (MDM enforces the right locking when entering / 278 // process) and thread-safety (MDM enforces the right locking when entering /
250 // leaving the MDP.DumpInto() call). This is to simplify the clients' design 279 // leaving the MDP.OnMemoryDump() call). This is to simplify the clients'
280 // design
251 // and not let the MDPs worry about locking. 281 // and not let the MDPs worry about locking.
252 // As regards thread affinity, depending on the MDP configuration (see 282 // As regards thread affinity, depending on the MDP configuration (see
253 // memory_dump_provider.h), the DumpInto() invocation can happen: 283 // memory_dump_provider.h), the OnMemoryDump() invocation can happen:
254 // - Synchronousy on the MDM thread, when MDP.task_runner() is not set. 284 // - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
255 // - Posted on MDP.task_runner(), when MDP.task_runner() is set. 285 // - Posted on MDP.task_runner(), when MDP.task_runner() is set.
256 { 286 {
257 AutoLock lock(lock_); 287 AutoLock lock(lock_);
258 for (auto dump_provider_iter = dump_providers_enabled_.begin(); 288 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
259 dump_provider_iter != dump_providers_enabled_.end();) { 289 MemoryDumpProvider* mdp = it->first;
260 // InvokeDumpProviderLocked will remove the MDP from the set if it fails. 290 MemoryDumpProviderInfo* mdp_info = &it->second;
261 MemoryDumpProvider* mdp = *dump_provider_iter; 291 if (mdp_info->disabled)
262 ++dump_provider_iter; 292 continue;
263 if (mdp->task_runner()) { 293 if (mdp_info->task_runner) {
264 // The DumpInto() call must be posted. 294 // The OnMemoryDump() call must be posted.
265 bool did_post_async_task = mdp->task_runner()->PostTask( 295 bool did_post_async_task = mdp_info->task_runner->PostTask(
266 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, 296 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
267 Unretained(this), Unretained(mdp), pmd_holder)); 297 Unretained(this), Unretained(mdp), pmd_holder));
268 // The thread underlying the TaskRunner might have gone away. 298 // The thread underlying the TaskRunner might have gone away.
269 if (did_post_async_task) 299 if (did_post_async_task)
270 ++pmd_holder->num_pending_async_requests; 300 ++pmd_holder->num_pending_async_requests;
271 } else { 301 } else {
272 // Invoke the dump provider synchronously. 302 // Invoke the dump provider synchronously.
273 did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd); 303 did_any_provider_dump |= InvokeDumpProviderLocked(mdp, pmd);
274 } 304 }
275 } 305 }
276 } // AutoLock 306 } // AutoLock
277 307
278 // If at least one synchronous provider did dump and there are no pending 308 // If at least one synchronous provider did dump and there are no pending
279 // asynchronous requests, add the dump to the trace and invoke the callback 309 // asynchronous requests, add the dump to the trace and invoke the callback
280 // straight away (FinalizeDumpAndAddToTrace() takes care of the callback). 310 // straight away (FinalizeDumpAndAddToTrace() takes care of the callback).
281 if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0) 311 if (did_any_provider_dump && pmd_holder->num_pending_async_requests == 0)
282 FinalizeDumpAndAddToTrace(pmd_holder); 312 FinalizeDumpAndAddToTrace(pmd_holder);
283 } 313 }
284 314
285 // Invokes the MemoryDumpProvider.DumpInto(), taking care of the failsafe logic 315 // Invokes the MemoryDumpProvider.OnMemoryDump(), taking care of the fail-safe
286 // which disables the dumper when failing (crbug.com/461788). 316 // logic which disables the dumper when failing (crbug.com/461788).
287 bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp, 317 bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
288 ProcessMemoryDump* pmd) { 318 ProcessMemoryDump* pmd) {
289 lock_.AssertAcquired(); 319 lock_.AssertAcquired();
290 dump_provider_currently_active_ = mdp; 320 bool dump_successful = mdp->OnMemoryDump(pmd);
291 bool dump_successful = mdp->DumpInto(pmd);
292 dump_provider_currently_active_ = nullptr;
293 if (!dump_successful) { 321 if (!dump_successful) {
294 LOG(ERROR) << "The memory dumper " << mdp->GetFriendlyName() 322 LOG(ERROR) << "The memory dumper failed, possibly due to sandboxing "
295 << " failed, possibly due to sandboxing (crbug.com/461788), " 323 "(crbug.com/461788), disabling it for current process. Try "
296 "disabling it for current process. Try restarting chrome " 324 "restarting chrome with the --no-sandbox switch.";
297 "with the --no-sandbox switch."; 325 dump_providers_.find(mdp)->second.disabled = true;
298 dump_providers_enabled_.erase(mdp);
299 } 326 }
300 return dump_successful; 327 return dump_successful;
301 } 328 }
302 329
303 // This is posted to arbitrary threads as a continuation of CreateProcessDump(), 330 // This is posted to arbitrary threads as a continuation of CreateProcessDump(),
304 // when one or more MemoryDumpProvider(s) require the DumpInto() call to happen 331 // when one or more MemoryDumpProvider(s) require the OnMemoryDump() call to
305 // on a different thread. 332 // happen on a different thread.
306 void MemoryDumpManager::ContinueAsyncProcessDump( 333 void MemoryDumpManager::ContinueAsyncProcessDump(
307 MemoryDumpProvider* mdp, 334 MemoryDumpProvider* mdp,
308 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) { 335 scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
309 bool should_finalize_dump = false; 336 bool should_finalize_dump = false;
310 { 337 {
311 // The lock here is to guarantee that different asynchronous dumps on 338 // The lock here is to guarantee that different asynchronous dumps on
312 // different threads are still serialized, so that the MemoryDumpProvider 339 // different threads are still serialized, so that the MemoryDumpProvider
313 // has a consistent view of the |pmd| argument passed. 340 // has a consistent view of the |pmd| argument passed.
314 AutoLock lock(lock_); 341 AutoLock lock(lock_);
315 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump; 342 ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
316 343
317 // Check if the MemoryDumpProvider is still there. It might have been 344 // Check if the MemoryDumpProvider is still there. It might have been
318 // destroyed and unregistered while hopping threads. 345 // destroyed and unregistered while hopping threads.
319 if (dump_providers_enabled_.count(mdp)) 346 if (dump_providers_.count(mdp))
320 InvokeDumpProviderLocked(mdp, pmd); 347 InvokeDumpProviderLocked(mdp, pmd);
321 348
322 // Finalize the dump appending it to the trace if this was the last 349 // Finalize the dump appending it to the trace if this was the last
323 // asynchronous request pending. 350 // asynchronous request pending.
324 --pmd_holder->num_pending_async_requests; 351 --pmd_holder->num_pending_async_requests;
325 if (pmd_holder->num_pending_async_requests == 0) 352 if (pmd_holder->num_pending_async_requests == 0)
326 should_finalize_dump = true; 353 should_finalize_dump = true;
327 } // AutoLock(lock_) 354 } // AutoLock(lock_)
328 355
329 if (should_finalize_dump) 356 if (should_finalize_dump)
330 FinalizeDumpAndAddToTrace(pmd_holder); 357 FinalizeDumpAndAddToTrace(pmd_holder);
331 } 358 }
332 359
333 void MemoryDumpManager::OnTraceLogEnabled() { 360 void MemoryDumpManager::OnTraceLogEnabled() {
334 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter 361 // TODO(primiano): at this point we query TraceLog::GetCurrentCategoryFilter
335 // to figure out (and cache) which dumpers should be enabled or not. 362 // to figure out (and cache) which dumpers should be enabled or not.
336 // For the moment piggy back everything on the generic "memory" category. 363 // For the moment piggy back everything on the generic "memory" category.
337 bool enabled; 364 bool enabled;
338 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); 365 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled);
339 366
340 AutoLock lock(lock_); 367 AutoLock lock(lock_);
341 368
342 // There is no point starting the tracing without a delegate. 369 // There is no point starting the tracing without a delegate.
343 if (!enabled || !delegate_) { 370 if (!enabled || !delegate_) {
344 dump_providers_enabled_.clear(); 371 // Disable all the providers.
372 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
373 it->second.disabled = true;
345 return; 374 return;
346 } 375 }
347 376
348 // Merge the dictionary of allocator attributes from all dump providers
349 // into the session state.
350 session_state_ = new MemoryDumpSessionState(); 377 session_state_ = new MemoryDumpSessionState();
351 for (const MemoryDumpProvider* mdp : dump_providers_registered_) { 378 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
352 session_state_->allocators_attributes_type_info.Update( 379 it->second.disabled = false;
353 mdp->allocator_attributes_type_info()); 380
354 }
355 dump_providers_enabled_ = dump_providers_registered_;
356 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); 381 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
357 382
358 if (delegate_->IsCoordinatorProcess()) { 383 if (delegate_->IsCoordinatorProcess()) {
359 periodic_dump_timer_.Start(FROM_HERE, 384 periodic_dump_timer_.Start(FROM_HERE,
360 TimeDelta::FromSeconds(kDumpIntervalSeconds), 385 TimeDelta::FromSeconds(kDumpIntervalSeconds),
361 base::Bind(&RequestPeriodicGlobalDump)); 386 base::Bind(&RequestPeriodicGlobalDump));
362 } 387 }
363 } 388 }
364 389
365 void MemoryDumpManager::OnTraceLogDisabled() { 390 void MemoryDumpManager::OnTraceLogDisabled() {
366 AutoLock lock(lock_); 391 AutoLock lock(lock_);
367 periodic_dump_timer_.Stop(); 392 periodic_dump_timer_.Stop();
368 dump_providers_enabled_.clear();
369 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); 393 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
370 session_state_ = nullptr; 394 session_state_ = nullptr;
371 } 395 }
372 396
397 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
398 const scoped_refptr<SingleThreadTaskRunner>& task_runner)
399 : task_runner(task_runner), disabled(false) {
400 }
401 MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {
402 }
403
373 } // namespace trace_event 404 } // namespace trace_event
374 } // namespace base 405 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/memory_dump_manager.h ('k') | base/trace_event/memory_dump_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698