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 <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> |
8 | 9 |
9 #include "base/atomic_sequence_num.h" | 10 #include "base/atomic_sequence_num.h" |
10 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
11 #include "base/command_line.h" | 12 #include "base/command_line.h" |
12 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
13 #include "base/thread_task_runner_handle.h" | 14 #include "base/thread_task_runner_handle.h" |
14 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
15 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 16 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
16 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 17 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
17 #include "base/trace_event/malloc_dump_provider.h" | 18 #include "base/trace_event/malloc_dump_provider.h" |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 dump_thread_->task_runner())); | 300 dump_thread_->task_runner())); |
300 } | 301 } |
301 | 302 |
302 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", | 303 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", |
303 TRACE_ID_MANGLE(args.dump_guid), | 304 TRACE_ID_MANGLE(args.dump_guid), |
304 TRACE_EVENT_FLAG_FLOW_OUT); | 305 TRACE_EVENT_FLAG_FLOW_OUT); |
305 | 306 |
306 // Start the thread hop. |dump_providers_| are kept sorted by thread, so | 307 // Start the thread hop. |dump_providers_| are kept sorted by thread, so |
307 // ContinueAsyncProcessDump will hop at most once per thread (w.r.t. thread | 308 // ContinueAsyncProcessDump will hop at most once per thread (w.r.t. thread |
308 // affinity specified by the MemoryDumpProvider(s) in RegisterDumpProvider()). | 309 // affinity specified by the MemoryDumpProvider(s) in RegisterDumpProvider()). |
309 ContinueAsyncProcessDump(pmd_async_state.Pass()); | 310 ContinueAsyncProcessDump(std::move(pmd_async_state)); |
310 } | 311 } |
311 | 312 |
312 // At most one ContinueAsyncProcessDump() can be active at any time for a given | 313 // At most one ContinueAsyncProcessDump() can be active at any time for a given |
313 // PMD, regardless of status of the |lock_|. |lock_| is used here purely to | 314 // PMD, regardless of status of the |lock_|. |lock_| is used here purely to |
314 // ensure consistency w.r.t. (un)registrations of |dump_providers_|. | 315 // ensure consistency w.r.t. (un)registrations of |dump_providers_|. |
315 // The linearization of dump providers' OnMemoryDump invocations is achieved by | 316 // The linearization of dump providers' OnMemoryDump invocations is achieved by |
316 // means of subsequent PostTask(s). | 317 // means of subsequent PostTask(s). |
317 // | 318 // |
318 // 1) Prologue: | 319 // 1) Prologue: |
319 // - Check if the dump provider is disabled, if so skip the dump. | 320 // - Check if the dump provider is disabled, if so skip the dump. |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 // Copy the callback + arguments just for the unlikley case in which | 372 // Copy the callback + arguments just for the unlikley case in which |
372 // PostTask fails. In such case the Bind helper will destroy the | 373 // PostTask fails. In such case the Bind helper will destroy the |
373 // pmd_async_state and we must keep a copy of the fields to notify the | 374 // pmd_async_state and we must keep a copy of the fields to notify the |
374 // abort. | 375 // abort. |
375 MemoryDumpCallback callback = pmd_async_state->callback; | 376 MemoryDumpCallback callback = pmd_async_state->callback; |
376 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 377 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
377 pmd_async_state->callback_task_runner; | 378 pmd_async_state->callback_task_runner; |
378 | 379 |
379 const bool did_post_task = task_runner->PostTask( | 380 const bool did_post_task = task_runner->PostTask( |
380 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, | 381 FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump, |
381 Unretained(this), Passed(pmd_async_state.Pass()))); | 382 Unretained(this), Passed(&pmd_async_state))); |
382 if (did_post_task) | 383 if (did_post_task) |
383 return; | 384 return; |
384 | 385 |
385 // The thread is gone. At this point the best thing we can do is to | 386 // The thread is gone. At this point the best thing we can do is to |
386 // disable the dump provider and abort this dump. | 387 // disable the dump provider and abort this dump. |
387 mdp_info->disabled = true; | 388 mdp_info->disabled = true; |
388 return AbortDumpLocked(callback, callback_task_runner, dump_guid); | 389 return AbortDumpLocked(callback, callback_task_runner, dump_guid); |
389 } | 390 } |
390 } // AutoLock(lock_) | 391 } // AutoLock(lock_) |
391 | 392 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 dump_providers_.erase(mdp_info); | 424 dump_providers_.erase(mdp_info); |
424 } | 425 } |
425 | 426 |
426 if (!skip_dump && !dump_successful) { | 427 if (!skip_dump && !dump_successful) { |
427 LOG(ERROR) << "MemoryDumpProvider \"" << dump_provider_name << "\" failed, " | 428 LOG(ERROR) << "MemoryDumpProvider \"" << dump_provider_name << "\" failed, " |
428 << "possibly due to sandboxing (crbug.com/461788)." | 429 << "possibly due to sandboxing (crbug.com/461788)." |
429 << "Disabling dumper for current process. Try --no-sandbox."; | 430 << "Disabling dumper for current process. Try --no-sandbox."; |
430 } | 431 } |
431 | 432 |
432 if (finalize) | 433 if (finalize) |
433 return FinalizeDumpAndAddToTrace(pmd_async_state.Pass()); | 434 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); |
434 | 435 |
435 ContinueAsyncProcessDump(pmd_async_state.Pass()); | 436 ContinueAsyncProcessDump(std::move(pmd_async_state)); |
436 } | 437 } |
437 | 438 |
438 // static | 439 // static |
439 void MemoryDumpManager::FinalizeDumpAndAddToTrace( | 440 void MemoryDumpManager::FinalizeDumpAndAddToTrace( |
440 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { | 441 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
441 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; | 442 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; |
442 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { | 443 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { |
443 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 444 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
444 pmd_async_state->callback_task_runner; | 445 pmd_async_state->callback_task_runner; |
445 callback_task_runner->PostTask( | 446 callback_task_runner->PostTask( |
446 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 447 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
447 Passed(pmd_async_state.Pass()))); | 448 Passed(&pmd_async_state))); |
448 return; | 449 return; |
449 } | 450 } |
450 | 451 |
451 TRACE_EVENT_WITH_FLOW0(kTraceCategory, | 452 TRACE_EVENT_WITH_FLOW0(kTraceCategory, |
452 "MemoryDumpManager::FinalizeDumpAndAddToTrace", | 453 "MemoryDumpManager::FinalizeDumpAndAddToTrace", |
453 TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN); | 454 TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN); |
454 | 455 |
455 for (const auto& kv : pmd_async_state->process_dumps) { | 456 for (const auto& kv : pmd_async_state->process_dumps) { |
456 ProcessId pid = kv.first; // kNullProcessId for the current process. | 457 ProcessId pid = kv.first; // kNullProcessId for the current process. |
457 ProcessMemoryDump* process_memory_dump = kv.second; | 458 ProcessMemoryDump* process_memory_dump = kv.second; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 if (heap_profiling_enabled_) { | 523 if (heap_profiling_enabled_) { |
523 // If heap profiling is enabled, the stack frame deduplicator will be in | 524 // If heap profiling is enabled, the stack frame deduplicator will be in |
524 // use. Add a metadata event to write its frames. | 525 // use. Add a metadata event to write its frames. |
525 stack_frame_deduplicator = new StackFrameDeduplicator; | 526 stack_frame_deduplicator = new StackFrameDeduplicator; |
526 TRACE_EVENT_API_ADD_METADATA_EVENT( | 527 TRACE_EVENT_API_ADD_METADATA_EVENT( |
527 "stackFrames", "stackFrames", | 528 "stackFrames", "stackFrames", |
528 scoped_refptr<ConvertableToTraceFormat>(stack_frame_deduplicator)); | 529 scoped_refptr<ConvertableToTraceFormat>(stack_frame_deduplicator)); |
529 } | 530 } |
530 | 531 |
531 DCHECK(!dump_thread_); | 532 DCHECK(!dump_thread_); |
532 dump_thread_ = dump_thread.Pass(); | 533 dump_thread_ = std::move(dump_thread); |
533 session_state_ = new MemoryDumpSessionState(stack_frame_deduplicator); | 534 session_state_ = new MemoryDumpSessionState(stack_frame_deduplicator); |
534 | 535 |
535 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { | 536 for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { |
536 it->disabled = false; | 537 it->disabled = false; |
537 it->consecutive_failures = 0; | 538 it->consecutive_failures = 0; |
538 } | 539 } |
539 | 540 |
540 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 541 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
541 | 542 |
542 // TODO(primiano): This is a temporary hack to disable periodic memory dumps | 543 // TODO(primiano): This is a temporary hack to disable periodic memory dumps |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 periodic_dump_timer_.Start(FROM_HERE, | 577 periodic_dump_timer_.Start(FROM_HERE, |
577 TimeDelta::FromMilliseconds(min_timer_period_ms), | 578 TimeDelta::FromMilliseconds(min_timer_period_ms), |
578 base::Bind(&RequestPeriodicGlobalDump)); | 579 base::Bind(&RequestPeriodicGlobalDump)); |
579 } | 580 } |
580 | 581 |
581 void MemoryDumpManager::OnTraceLogDisabled() { | 582 void MemoryDumpManager::OnTraceLogDisabled() { |
582 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 583 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
583 scoped_ptr<Thread> dump_thread; | 584 scoped_ptr<Thread> dump_thread; |
584 { | 585 { |
585 AutoLock lock(lock_); | 586 AutoLock lock(lock_); |
586 dump_thread = dump_thread_.Pass(); | 587 dump_thread = std::move(dump_thread_); |
587 session_state_ = nullptr; | 588 session_state_ = nullptr; |
588 } | 589 } |
589 | 590 |
590 // Thread stops are blocking and must be performed outside of the |lock_| | 591 // Thread stops are blocking and must be performed outside of the |lock_| |
591 // or will deadlock (e.g., if ContinueAsyncProcessDump() tries to acquire it). | 592 // or will deadlock (e.g., if ContinueAsyncProcessDump() tries to acquire it). |
592 periodic_dump_timer_.Stop(); | 593 periodic_dump_timer_.Stop(); |
593 if (dump_thread) | 594 if (dump_thread) |
594 dump_thread->Stop(); | 595 dump_thread->Stop(); |
595 } | 596 } |
596 | 597 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 dump_thread_task_runner(dump_thread_task_runner) {} | 639 dump_thread_task_runner(dump_thread_task_runner) {} |
639 | 640 |
640 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 641 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
641 } | 642 } |
642 | 643 |
643 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: | 644 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: |
644 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { | 645 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { |
645 auto iter = process_dumps.find(pid); | 646 auto iter = process_dumps.find(pid); |
646 if (iter == process_dumps.end()) { | 647 if (iter == process_dumps.end()) { |
647 scoped_ptr<ProcessMemoryDump> new_pmd(new ProcessMemoryDump(session_state)); | 648 scoped_ptr<ProcessMemoryDump> new_pmd(new ProcessMemoryDump(session_state)); |
648 iter = process_dumps.insert(pid, new_pmd.Pass()).first; | 649 iter = process_dumps.insert(pid, std::move(new_pmd)).first; |
649 } | 650 } |
650 return iter->second; | 651 return iter->second; |
651 } | 652 } |
652 | 653 |
653 } // namespace trace_event | 654 } // namespace trace_event |
654 } // namespace base | 655 } // namespace base |
OLD | NEW |