Chromium Code Reviews| 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 <inttypes.h> | |
| 8 #include <stdio.h> | |
| 9 | |
| 7 #include <algorithm> | 10 #include <algorithm> |
| 8 #include <utility> | 11 #include <utility> |
| 9 | 12 |
| 10 #include "base/allocator/features.h" | 13 #include "base/allocator/features.h" |
| 11 #include "base/atomic_sequence_num.h" | 14 #include "base/atomic_sequence_num.h" |
| 12 #include "base/base_switches.h" | 15 #include "base/base_switches.h" |
| 13 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 14 #include "base/compiler_specific.h" | 17 #include "base/compiler_specific.h" |
| 15 #include "base/debug/alias.h" | 18 #include "base/debug/alias.h" |
| 16 #include "base/debug/debugging_flags.h" | 19 #include "base/debug/debugging_flags.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 "gpu::MappedMemoryManager", | 78 "gpu::MappedMemoryManager", |
| 76 "gpu::RenderbufferManager", | 79 "gpu::RenderbufferManager", |
| 77 "BlacklistTestDumpProvider" // for testing | 80 "BlacklistTestDumpProvider" // for testing |
| 78 }; | 81 }; |
| 79 | 82 |
| 80 // Callback wrapper to hook upon the completion of RequestGlobalDump() and | 83 // Callback wrapper to hook upon the completion of RequestGlobalDump() and |
| 81 // inject trace markers. | 84 // inject trace markers. |
| 82 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, | 85 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, |
| 83 uint64_t dump_guid, | 86 uint64_t dump_guid, |
| 84 bool success) { | 87 bool success) { |
| 85 TRACE_EVENT_NESTABLE_ASYNC_END1( | 88 char guid_str[20]; |
| 86 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", | 89 sprintf(guid_str, "0x%" PRIx64, dump_guid); |
|
ssid
2017/03/28 20:21:56
Do we need 0x?
base::Uint64ToString looks better,
Primiano Tucci (use gerrit)
2017/03/28 23:13:15
not too strong but helps debuggin to copy/paste an
| |
| 87 TRACE_ID_MANGLE(dump_guid), "success", success); | 90 TRACE_EVENT_NESTABLE_ASYNC_END2(MemoryDumpManager::kTraceCategory, |
| 91 "GlobalMemoryDump", TRACE_ID_LOCAL(dump_guid), | |
| 92 "dump_guid", TRACE_STR_COPY(guid_str), | |
| 93 "success", success); | |
| 88 | 94 |
| 89 if (!wrapped_callback.is_null()) { | 95 if (!wrapped_callback.is_null()) { |
| 90 wrapped_callback.Run(dump_guid, success); | 96 wrapped_callback.Run(dump_guid, success); |
| 91 wrapped_callback.Reset(); | 97 wrapped_callback.Reset(); |
| 92 } | 98 } |
| 93 } | 99 } |
| 94 | 100 |
| 95 // Proxy class which wraps a ConvertableToTraceFormat owned by the | 101 // Proxy class which wraps a ConvertableToTraceFormat owned by the |
| 96 // |session_state| into a proxy object that can be added to the trace event log. | 102 // |session_state| into a proxy object that can be added to the trace event log. |
| 97 // This is to solve the problem that the MemoryDumpSessionState is refcounted | 103 // This is to solve the problem that the MemoryDumpSessionState is refcounted |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 callback.Run(0u /* guid */, false /* success */); | 462 callback.Run(0u /* guid */, false /* success */); |
| 457 return; | 463 return; |
| 458 } | 464 } |
| 459 | 465 |
| 460 const uint64_t guid = | 466 const uint64_t guid = |
| 461 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 467 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
| 462 | 468 |
| 463 // Creates an async event to keep track of the global dump evolution. | 469 // Creates an async event to keep track of the global dump evolution. |
| 464 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 470 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
| 465 // the real |callback| provided by the caller. | 471 // the real |callback| provided by the caller. |
| 466 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "GlobalMemoryDump", | 472 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
| 467 TRACE_ID_MANGLE(guid)); | 473 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", |
| 474 MemoryDumpTypeToString(dump_type), "level_of_detail", | |
| 475 MemoryDumpLevelOfDetailToString(level_of_detail)); | |
| 468 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); | 476 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); |
| 469 | 477 |
| 470 // The delegate will coordinate the IPC broadcast and at some point invoke | 478 // The delegate will coordinate the IPC broadcast and at some point invoke |
| 471 // CreateProcessDump() to get a dump for the current process. | 479 // CreateProcessDump() to get a dump for the current process. |
| 472 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; | 480 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; |
| 473 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); | 481 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); |
| 474 } | 482 } |
| 475 | 483 |
| 476 void MemoryDumpManager::RequestGlobalDump( | 484 void MemoryDumpManager::RequestGlobalDump( |
| 477 MemoryDumpType dump_type, | 485 MemoryDumpType dump_type, |
| 478 MemoryDumpLevelOfDetail level_of_detail) { | 486 MemoryDumpLevelOfDetail level_of_detail) { |
| 479 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); | 487 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); |
| 480 } | 488 } |
| 481 | 489 |
| 482 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( | 490 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( |
| 483 MemoryDumpProvider* provider) { | 491 MemoryDumpProvider* provider) { |
| 484 AutoLock lock(lock_); | 492 AutoLock lock(lock_); |
| 485 | 493 |
| 486 for (const auto& info : dump_providers_) { | 494 for (const auto& info : dump_providers_) { |
| 487 if (info->dump_provider == provider) | 495 if (info->dump_provider == provider) |
| 488 return true; | 496 return true; |
| 489 } | 497 } |
| 490 return false; | 498 return false; |
| 491 } | 499 } |
| 492 | 500 |
| 493 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 501 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, |
| 494 const MemoryDumpCallback& callback) { | 502 const MemoryDumpCallback& callback) { |
| 495 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "ProcessMemoryDump", | 503 char guid_str[20]; |
| 496 TRACE_ID_MANGLE(args.dump_guid)); | 504 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); |
| 505 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", | |
| 506 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", | |
| 507 TRACE_STR_COPY(guid_str)); | |
|
ssid
2017/03/28 20:21:56
For ProcessMemoryDump the guid is added at the BEG
Primiano Tucci (use gerrit)
2017/03/28 23:13:14
Aha I knew, well spotted.
ssid
2017/03/28 23:21:45
LOL!
| |
| 497 | 508 |
| 498 // If argument filter is enabled then only background mode dumps should be | 509 // If argument filter is enabled then only background mode dumps should be |
| 499 // allowed. In case the trace config passed for background tracing session | 510 // allowed. In case the trace config passed for background tracing session |
| 500 // missed the allowed modes argument, it crashes here instead of creating | 511 // missed the allowed modes argument, it crashes here instead of creating |
| 501 // unexpected dumps. | 512 // unexpected dumps. |
| 502 if (TraceLog::GetInstance() | 513 if (TraceLog::GetInstance() |
| 503 ->GetCurrentTraceConfig() | 514 ->GetCurrentTraceConfig() |
| 504 .IsArgumentFilterEnabled()) { | 515 .IsArgumentFilterEnabled()) { |
| 505 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); | 516 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); |
| 506 } | 517 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 518 | 529 |
| 519 // Safety check to prevent reaching here without calling RequestGlobalDump, | 530 // Safety check to prevent reaching here without calling RequestGlobalDump, |
| 520 // with disallowed modes. If |session_state_| is null then tracing is | 531 // with disallowed modes. If |session_state_| is null then tracing is |
| 521 // disabled. | 532 // disabled. |
| 522 CHECK(!session_state_ || | 533 CHECK(!session_state_ || |
| 523 session_state_->IsDumpModeAllowed(args.level_of_detail)); | 534 session_state_->IsDumpModeAllowed(args.level_of_detail)); |
| 524 | 535 |
| 525 MemoryDumpScheduler::GetInstance()->NotifyDumpTriggered(); | 536 MemoryDumpScheduler::GetInstance()->NotifyDumpTriggered(); |
| 526 } | 537 } |
| 527 | 538 |
| 528 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", | |
| 529 TRACE_ID_MANGLE(args.dump_guid), | |
| 530 TRACE_EVENT_FLAG_FLOW_OUT); | |
| 531 | |
| 532 // Start the process dump. This involves task runner hops as specified by the | 539 // Start the process dump. This involves task runner hops as specified by the |
| 533 // MemoryDumpProvider(s) in RegisterDumpProvider()). | 540 // MemoryDumpProvider(s) in RegisterDumpProvider()). |
| 534 SetupNextMemoryDump(std::move(pmd_async_state)); | 541 SetupNextMemoryDump(std::move(pmd_async_state)); |
| 535 } | 542 } |
| 536 | 543 |
| 537 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A | 544 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A |
| 538 // PostTask is always required for a generic SequencedTaskRunner to ensure that | 545 // PostTask is always required for a generic SequencedTaskRunner to ensure that |
| 539 // no other task is running on it concurrently. SetupNextMemoryDump() and | 546 // no other task is running on it concurrently. SetupNextMemoryDump() and |
| 540 // InvokeOnMemoryDump() are called alternatively which linearizes the dump | 547 // InvokeOnMemoryDump() are called alternatively which linearizes the dump |
| 541 // provider's OnMemoryDump invocations. | 548 // provider's OnMemoryDump invocations. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 665 mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) { | 672 mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) { |
| 666 mdpinfo->disabled = true; | 673 mdpinfo->disabled = true; |
| 667 LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name | 674 LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name |
| 668 << "\". Dump failed multiple times consecutively."; | 675 << "\". Dump failed multiple times consecutively."; |
| 669 } | 676 } |
| 670 should_dump = !mdpinfo->disabled; | 677 should_dump = !mdpinfo->disabled; |
| 671 } // AutoLock lock(lock_); | 678 } // AutoLock lock(lock_); |
| 672 | 679 |
| 673 if (should_dump) { | 680 if (should_dump) { |
| 674 // Invoke the dump provider. | 681 // Invoke the dump provider. |
| 675 TRACE_EVENT_WITH_FLOW1(kTraceCategory, | 682 TRACE_EVENT1(kTraceCategory, "MemoryDumpManager::InvokeOnMemoryDump", |
| 676 "MemoryDumpManager::InvokeOnMemoryDump", | 683 "dump_provider.name", mdpinfo->name); |
| 677 TRACE_ID_MANGLE(pmd_async_state->req_args.dump_guid), | |
| 678 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, | |
| 679 "dump_provider.name", mdpinfo->name); | |
| 680 | 684 |
| 681 // A stack allocated string with dump provider name is useful to debug | 685 // A stack allocated string with dump provider name is useful to debug |
| 682 // crashes while invoking dump after a |dump_provider| is not unregistered | 686 // crashes while invoking dump after a |dump_provider| is not unregistered |
| 683 // in safe way. | 687 // in safe way. |
| 684 // TODO(ssid): Remove this after fixing crbug.com/643438. | 688 // TODO(ssid): Remove this after fixing crbug.com/643438. |
| 685 char provider_name_for_debugging[16]; | 689 char provider_name_for_debugging[16]; |
| 686 strncpy(provider_name_for_debugging, mdpinfo->name, | 690 strncpy(provider_name_for_debugging, mdpinfo->name, |
| 687 sizeof(provider_name_for_debugging) - 1); | 691 sizeof(provider_name_for_debugging) - 1); |
| 688 provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0'; | 692 provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0'; |
| 689 base::debug::Alias(provider_name_for_debugging); | 693 base::debug::Alias(provider_name_for_debugging); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 747 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; | 751 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; |
| 748 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { | 752 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { |
| 749 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 753 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
| 750 pmd_async_state->callback_task_runner; | 754 pmd_async_state->callback_task_runner; |
| 751 callback_task_runner->PostTask( | 755 callback_task_runner->PostTask( |
| 752 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 756 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
| 753 Passed(&pmd_async_state))); | 757 Passed(&pmd_async_state))); |
| 754 return; | 758 return; |
| 755 } | 759 } |
| 756 | 760 |
| 757 TRACE_EVENT_WITH_FLOW0(kTraceCategory, | 761 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); |
| 758 "MemoryDumpManager::FinalizeDumpAndAddToTrace", | |
| 759 TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN); | |
| 760 | 762 |
| 761 // The results struct to fill. | 763 // The results struct to fill. |
| 762 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 764 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
| 763 MemoryDumpCallbackResult result; | 765 MemoryDumpCallbackResult result; |
| 764 | 766 |
| 765 for (const auto& kv : pmd_async_state->process_dumps) { | 767 for (const auto& kv : pmd_async_state->process_dumps) { |
| 766 ProcessId pid = kv.first; // kNullProcessId for the current process. | 768 ProcessId pid = kv.first; // kNullProcessId for the current process. |
| 767 ProcessMemoryDump* process_memory_dump = kv.second.get(); | 769 ProcessMemoryDump* process_memory_dump = kv.second.get(); |
| 768 std::unique_ptr<TracedValue> traced_value(new TracedValue); | 770 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
| 769 process_memory_dump->AsValueInto(traced_value.get()); | 771 process_memory_dump->AsValueInto(traced_value.get()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 815 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" | 817 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" |
| 816 << " the dump was completed"; | 818 << " the dump was completed"; |
| 817 } | 819 } |
| 818 | 820 |
| 819 if (!pmd_async_state->callback.is_null()) { | 821 if (!pmd_async_state->callback.is_null()) { |
| 820 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful); | 822 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful); |
| 821 pmd_async_state->callback.Reset(); | 823 pmd_async_state->callback.Reset(); |
| 822 } | 824 } |
| 823 | 825 |
| 824 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 826 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
| 825 TRACE_ID_MANGLE(dump_guid)); | 827 TRACE_ID_LOCAL(dump_guid)); |
| 826 } | 828 } |
| 827 | 829 |
| 828 void MemoryDumpManager::OnTraceLogEnabled() { | 830 void MemoryDumpManager::OnTraceLogEnabled() { |
| 829 bool enabled; | 831 bool enabled; |
| 830 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); | 832 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); |
| 831 if (!enabled) | 833 if (!enabled) |
| 832 return; | 834 return; |
| 833 | 835 |
| 834 // Initialize the TraceLog for the current thread. This is to avoid that the | 836 // Initialize the TraceLog for the current thread. This is to avoid that the |
| 835 // TraceLog memory dump provider is registered lazily in the PostTask() below | 837 // TraceLog memory dump provider is registered lazily in the PostTask() below |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1008 if (iter == process_dumps.end()) { | 1010 if (iter == process_dumps.end()) { |
| 1009 std::unique_ptr<ProcessMemoryDump> new_pmd( | 1011 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 1010 new ProcessMemoryDump(session_state, dump_args)); | 1012 new ProcessMemoryDump(session_state, dump_args)); |
| 1011 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 1013 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 1012 } | 1014 } |
| 1013 return iter->second.get(); | 1015 return iter->second.get(); |
| 1014 } | 1016 } |
| 1015 | 1017 |
| 1016 } // namespace trace_event | 1018 } // namespace trace_event |
| 1017 } // namespace base | 1019 } // namespace base |
| OLD | NEW |