| Index: base/trace_event/memory_dump_manager.cc
|
| diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc
|
| index 859e8e02dc75dfca8f5e5726c7db7f131d9dc34d..1e4d8229aef0b2a69ae9cf9f51f6547dc64203da 100644
|
| --- a/base/trace_event/memory_dump_manager.cc
|
| +++ b/base/trace_event/memory_dump_manager.cc
|
| @@ -12,12 +12,22 @@
|
| #include "base/trace_event/memory_dump_session_state.h"
|
| #include "base/trace_event/process_memory_dump.h"
|
| #include "base/trace_event/trace_event_argument.h"
|
| +#include "build/build_config.h"
|
| +
|
| +#if !defined(OS_NACL)
|
| +#include "base/trace_event/process_memory_totals_dump_provider.h"
|
| +#endif
|
|
|
| #if defined(OS_LINUX) || defined(OS_ANDROID)
|
| #include "base/trace_event/malloc_dump_provider.h"
|
| #include "base/trace_event/process_memory_maps_dump_provider.h"
|
| -#include "base/trace_event/process_memory_totals_dump_provider.h"
|
| -#elif defined(OS_WIN)
|
| +#endif
|
| +
|
| +#if defined(OS_ANDROID)
|
| +#include "base/trace_event/java_heap_dump_provider_android.h"
|
| +#endif
|
| +
|
| +#if defined(OS_WIN)
|
| #include "base/trace_event/winheap_dump_provider_win.h"
|
| #endif
|
|
|
| @@ -144,8 +154,7 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) {
|
| }
|
|
|
| MemoryDumpManager::MemoryDumpManager()
|
| - : dump_provider_currently_active_(nullptr),
|
| - delegate_(nullptr),
|
| + : delegate_(nullptr),
|
| memory_tracing_enabled_(0),
|
| skip_core_dumpers_auto_registration_for_testing_(false) {
|
| g_next_guid.GetNext(); // Make sure that first guid is not zero.
|
| @@ -162,12 +171,21 @@ void MemoryDumpManager::Initialize() {
|
| if (skip_core_dumpers_auto_registration_for_testing_)
|
| return;
|
|
|
| -#if defined(OS_LINUX) || defined(OS_ANDROID)
|
| // Enable the core dump providers.
|
| +#if !defined(OS_NACL)
|
| RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance());
|
| +#endif
|
| +
|
| +#if defined(OS_LINUX) || defined(OS_ANDROID)
|
| RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance());
|
| RegisterDumpProvider(MallocDumpProvider::GetInstance());
|
| -#elif defined(OS_WIN)
|
| +#endif
|
| +
|
| +#if defined(OS_ANDROID)
|
| + RegisterDumpProvider(JavaHeapDumpProvider::GetInstance());
|
| +#endif
|
| +
|
| +#if defined(OS_WIN)
|
| RegisterDumpProvider(WinHeapDumpProvider::GetInstance());
|
| #endif
|
| }
|
| @@ -178,30 +196,41 @@ void MemoryDumpManager::SetDelegate(MemoryDumpManagerDelegate* delegate) {
|
| delegate_ = delegate;
|
| }
|
|
|
| -void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
|
| +void MemoryDumpManager::RegisterDumpProvider(
|
| + MemoryDumpProvider* mdp,
|
| + const scoped_refptr<SingleThreadTaskRunner>& task_runner) {
|
| + MemoryDumpProviderInfo mdp_info(task_runner);
|
| AutoLock lock(lock_);
|
| - dump_providers_registered_.insert(mdp);
|
| + dump_providers_.insert(std::make_pair(mdp, mdp_info));
|
| +}
|
| +
|
| +void MemoryDumpManager::RegisterDumpProvider(MemoryDumpProvider* mdp) {
|
| + RegisterDumpProvider(mdp, nullptr);
|
| }
|
|
|
| void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
|
| AutoLock lock(lock_);
|
|
|
| + auto it = dump_providers_.find(mdp);
|
| + if (it == dump_providers_.end())
|
| + return;
|
| +
|
| + const MemoryDumpProviderInfo& mdp_info = it->second;
|
| // Unregistration of a MemoryDumpProvider while tracing is ongoing is safe
|
| // only if the MDP has specified a thread affinity (via task_runner()) AND
|
| // the unregistration happens on the same thread (so the MDP cannot unregister
|
| - // and DumpInto() at the same time).
|
| + // and OnMemoryDump() at the same time).
|
| // Otherwise, it is not possible to guarantee that its unregistration is
|
| // race-free. If you hit this DCHECK, your MDP has a bug.
|
| DCHECK_IMPLIES(
|
| subtle::NoBarrier_Load(&memory_tracing_enabled_),
|
| - mdp->task_runner() && mdp->task_runner()->BelongsToCurrentThread())
|
| - << "The MemoryDumpProvider " << mdp->GetFriendlyName() << " attempted to "
|
| - << "unregister itself in a racy way. Please file a crbug.";
|
| + mdp_info.task_runner && mdp_info.task_runner->BelongsToCurrentThread())
|
| + << "The MemoryDumpProvider attempted to unregister itself in a racy way. "
|
| + << " Please file a crbug.";
|
|
|
| // Remove from the enabled providers list. This is to deal with the case that
|
| // UnregisterDumpProvider is called while the trace is enabled.
|
| - dump_providers_enabled_.erase(mdp);
|
| - dump_providers_registered_.erase(mdp);
|
| + dump_providers_.erase(it);
|
| }
|
|
|
| void MemoryDumpManager::RequestGlobalDump(
|
| @@ -244,25 +273,26 @@ void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
|
| ProcessMemoryDump* pmd = &pmd_holder->process_memory_dump;
|
| bool did_any_provider_dump = false;
|
|
|
| - // Iterate over the active dump providers and invoke DumpInto(pmd).
|
| + // Iterate over the active dump providers and invoke OnMemoryDump(pmd).
|
| // The MDM guarantees linearity (at most one MDP is active within one
|
| // process) and thread-safety (MDM enforces the right locking when entering /
|
| - // leaving the MDP.DumpInto() call). This is to simplify the clients' design
|
| + // leaving the MDP.OnMemoryDump() call). This is to simplify the clients'
|
| + // design
|
| // and not let the MDPs worry about locking.
|
| // As regards thread affinity, depending on the MDP configuration (see
|
| - // memory_dump_provider.h), the DumpInto() invocation can happen:
|
| + // memory_dump_provider.h), the OnMemoryDump() invocation can happen:
|
| // - Synchronousy on the MDM thread, when MDP.task_runner() is not set.
|
| // - Posted on MDP.task_runner(), when MDP.task_runner() is set.
|
| {
|
| AutoLock lock(lock_);
|
| - for (auto dump_provider_iter = dump_providers_enabled_.begin();
|
| - dump_provider_iter != dump_providers_enabled_.end();) {
|
| - // InvokeDumpProviderLocked will remove the MDP from the set if it fails.
|
| - MemoryDumpProvider* mdp = *dump_provider_iter;
|
| - ++dump_provider_iter;
|
| - if (mdp->task_runner()) {
|
| - // The DumpInto() call must be posted.
|
| - bool did_post_async_task = mdp->task_runner()->PostTask(
|
| + for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) {
|
| + MemoryDumpProvider* mdp = it->first;
|
| + MemoryDumpProviderInfo* mdp_info = &it->second;
|
| + if (mdp_info->disabled)
|
| + continue;
|
| + if (mdp_info->task_runner) {
|
| + // The OnMemoryDump() call must be posted.
|
| + bool did_post_async_task = mdp_info->task_runner->PostTask(
|
| FROM_HERE, Bind(&MemoryDumpManager::ContinueAsyncProcessDump,
|
| Unretained(this), Unretained(mdp), pmd_holder));
|
| // The thread underlying the TaskRunner might have gone away.
|
| @@ -282,27 +312,24 @@ void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args,
|
| FinalizeDumpAndAddToTrace(pmd_holder);
|
| }
|
|
|
| -// Invokes the MemoryDumpProvider.DumpInto(), taking care of the failsafe logic
|
| -// which disables the dumper when failing (crbug.com/461788).
|
| +// Invokes the MemoryDumpProvider.OnMemoryDump(), taking care of the fail-safe
|
| +// logic which disables the dumper when failing (crbug.com/461788).
|
| bool MemoryDumpManager::InvokeDumpProviderLocked(MemoryDumpProvider* mdp,
|
| ProcessMemoryDump* pmd) {
|
| lock_.AssertAcquired();
|
| - dump_provider_currently_active_ = mdp;
|
| - bool dump_successful = mdp->DumpInto(pmd);
|
| - dump_provider_currently_active_ = nullptr;
|
| + bool dump_successful = mdp->OnMemoryDump(pmd);
|
| if (!dump_successful) {
|
| - LOG(ERROR) << "The memory dumper " << mdp->GetFriendlyName()
|
| - << " failed, possibly due to sandboxing (crbug.com/461788), "
|
| - "disabling it for current process. Try restarting chrome "
|
| - "with the --no-sandbox switch.";
|
| - dump_providers_enabled_.erase(mdp);
|
| + LOG(ERROR) << "The memory dumper failed, possibly due to sandboxing "
|
| + "(crbug.com/461788), disabling it for current process. Try "
|
| + "restarting chrome with the --no-sandbox switch.";
|
| + dump_providers_.find(mdp)->second.disabled = true;
|
| }
|
| return dump_successful;
|
| }
|
|
|
| // This is posted to arbitrary threads as a continuation of CreateProcessDump(),
|
| -// when one or more MemoryDumpProvider(s) require the DumpInto() call to happen
|
| -// on a different thread.
|
| +// when one or more MemoryDumpProvider(s) require the OnMemoryDump() call to
|
| +// happen on a different thread.
|
| void MemoryDumpManager::ContinueAsyncProcessDump(
|
| MemoryDumpProvider* mdp,
|
| scoped_refptr<ProcessMemoryDumpHolder> pmd_holder) {
|
| @@ -316,7 +343,7 @@ void MemoryDumpManager::ContinueAsyncProcessDump(
|
|
|
| // Check if the MemoryDumpProvider is still there. It might have been
|
| // destroyed and unregistered while hopping threads.
|
| - if (dump_providers_enabled_.count(mdp))
|
| + if (dump_providers_.count(mdp))
|
| InvokeDumpProviderLocked(mdp, pmd);
|
|
|
| // Finalize the dump appending it to the trace if this was the last
|
| @@ -341,18 +368,16 @@ void MemoryDumpManager::OnTraceLogEnabled() {
|
|
|
| // There is no point starting the tracing without a delegate.
|
| if (!enabled || !delegate_) {
|
| - dump_providers_enabled_.clear();
|
| + // Disable all the providers.
|
| + for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
|
| + it->second.disabled = true;
|
| return;
|
| }
|
|
|
| - // Merge the dictionary of allocator attributes from all dump providers
|
| - // into the session state.
|
| session_state_ = new MemoryDumpSessionState();
|
| - for (const MemoryDumpProvider* mdp : dump_providers_registered_) {
|
| - session_state_->allocators_attributes_type_info.Update(
|
| - mdp->allocator_attributes_type_info());
|
| - }
|
| - dump_providers_enabled_ = dump_providers_registered_;
|
| + for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it)
|
| + it->second.disabled = false;
|
| +
|
| subtle::NoBarrier_Store(&memory_tracing_enabled_, 1);
|
|
|
| if (delegate_->IsCoordinatorProcess()) {
|
| @@ -365,10 +390,16 @@ void MemoryDumpManager::OnTraceLogEnabled() {
|
| void MemoryDumpManager::OnTraceLogDisabled() {
|
| AutoLock lock(lock_);
|
| periodic_dump_timer_.Stop();
|
| - dump_providers_enabled_.clear();
|
| subtle::NoBarrier_Store(&memory_tracing_enabled_, 0);
|
| session_state_ = nullptr;
|
| }
|
|
|
| +MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo(
|
| + const scoped_refptr<SingleThreadTaskRunner>& task_runner)
|
| + : task_runner(task_runner), disabled(false) {
|
| +}
|
| +MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {
|
| +}
|
| +
|
| } // namespace trace_event
|
| } // namespace base
|
|
|