| 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 c8be8f89312a34d5b0bdd3996c3abebbc143f10b..cbed2380039c78bea20c3dcc7c602000f59d61bf 100644
|
| --- a/base/trace_event/memory_dump_manager.cc
|
| +++ b/base/trace_event/memory_dump_manager.cc
|
| @@ -6,6 +6,7 @@
|
|
|
| #include <algorithm>
|
|
|
| +#include "base/atomic_sequence_num.h"
|
| #include "base/compiler_specific.h"
|
| #include "base/trace_event/memory_dump_provider.h"
|
| #include "base/trace_event/process_memory_dump.h"
|
| @@ -15,7 +16,27 @@ namespace base {
|
| namespace trace_event {
|
|
|
| namespace {
|
| +
|
| MemoryDumpManager* g_instance_for_testing = nullptr;
|
| +const int kTraceEventNumArgs = 1;
|
| +const char* kTraceEventArgNames[] = {"dumps"};
|
| +const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE};
|
| +StaticAtomicSequenceNumber g_next_guid;
|
| +
|
| +const char* DumpPointTypeToString(const DumpPointType& dump_point_type) {
|
| + switch (dump_point_type) {
|
| + case DumpPointType::TASK_BEGIN:
|
| + return "TASK_BEGIN";
|
| + case DumpPointType::TASK_END:
|
| + return "TASK_END";
|
| + case DumpPointType::PERIODIC_INTERVAL:
|
| + return "PERIODIC_INTERVAL";
|
| + case DumpPointType::EXPLICITLY_TRIGGERED:
|
| + return "EXPLICITLY_TRIGGERED";
|
| + }
|
| + NOTREACHED();
|
| + return "UNKNOWN";
|
| +}
|
| }
|
|
|
| // TODO(primiano): this should be smarter and should do something similar to
|
| @@ -76,13 +97,18 @@ void MemoryDumpManager::UnregisterDumpProvider(MemoryDumpProvider* mdp) {
|
| dump_providers_enabled_.erase(it);
|
| }
|
|
|
| -void MemoryDumpManager::RequestDumpPoint(DumpPointType type) {
|
| - // TODO(primiano): this will have more logic, IPC broadcast & co.
|
| +void MemoryDumpManager::RequestDumpPoint(DumpPointType dump_point_type) {
|
| + // TODO(primiano): this will have more logic to coordinate dump points across
|
| + // multiple processes via IPC. See crbug.com/462930.
|
| +
|
| // Bail out immediately if tracing is not enabled at all.
|
| if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)))
|
| return;
|
|
|
| - CreateLocalDumpPoint();
|
| + // TODO(primiano): Make guid actually unique (cross-process) by hashing it
|
| + // with the PID. See crbug.com/462931 for details.
|
| + const uint64 guid = g_next_guid.GetNext();
|
| + CreateLocalDumpPoint(dump_point_type, guid);
|
| }
|
|
|
| void MemoryDumpManager::BroadcastDumpRequest() {
|
| @@ -90,17 +116,44 @@ void MemoryDumpManager::BroadcastDumpRequest() {
|
| }
|
|
|
| // Creates a dump point for the current process and appends it to the trace.
|
| -void MemoryDumpManager::CreateLocalDumpPoint() {
|
| - AutoLock lock(lock_);
|
| +void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type,
|
| + uint64 guid) {
|
| + bool did_any_provider_dump = false;
|
| scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump());
|
|
|
| - for (MemoryDumpProvider* dump_provider : dump_providers_enabled_) {
|
| - dump_provider->DumpInto(pmd.get());
|
| + // Serialize dump point generation so that memory dump providers don't have to
|
| + // deal with thread safety.
|
| + {
|
| + AutoLock lock(lock_);
|
| + for (auto it = dump_providers_enabled_.begin();
|
| + it != dump_providers_enabled_.end();) {
|
| + MemoryDumpProvider* dump_provider = *it;
|
| + if (dump_provider->DumpInto(pmd.get())) {
|
| + did_any_provider_dump = true;
|
| + ++it;
|
| + } else {
|
| + LOG(ERROR) << "The memory dumper " << dump_provider->GetFriendlyName()
|
| + << " failed, possibly due to sandboxing (crbug.com/461788), "
|
| + "disabling it for current process. Try restarting chrome "
|
| + "with the --no-sandbox switch.";
|
| + it = dump_providers_enabled_.erase(it);
|
| + }
|
| + }
|
| }
|
|
|
| - scoped_refptr<TracedValue> value(new TracedValue());
|
| - pmd->AsValueInto(value.get());
|
| - // TODO(primiano): add the dump point to the trace at this point.
|
| + // Don't create a dump point if all the dumpers failed.
|
| + if (!did_any_provider_dump)
|
| + return;
|
| +
|
| + scoped_refptr<ConvertableToTraceFormat> event_value(new TracedValue());
|
| + pmd->AsValueInto(static_cast<TracedValue*>(event_value.get()));
|
| + const char* const event_name = DumpPointTypeToString(dump_point_type);
|
| +
|
| + TRACE_EVENT_API_ADD_TRACE_EVENT(
|
| + TRACE_EVENT_PHASE_MEMORY_DUMP,
|
| + TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, guid,
|
| + kTraceEventNumArgs, kTraceEventArgNames, kTraceEventArgTypes,
|
| + NULL /* arg_values */, &event_value, TRACE_EVENT_FLAG_HAS_ID);
|
| }
|
|
|
| void MemoryDumpManager::OnTraceLogEnabled() {
|
|
|