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 |