| 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 |