| 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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 "gpu::MappedMemoryManager", | 76 "gpu::MappedMemoryManager", |
| 74 "gpu::RenderbufferManager", | 77 "gpu::RenderbufferManager", |
| 75 "BlacklistTestDumpProvider" // for testing | 78 "BlacklistTestDumpProvider" // for testing |
| 76 }; | 79 }; |
| 77 | 80 |
| 78 // Callback wrapper to hook upon the completion of RequestGlobalDump() and | 81 // Callback wrapper to hook upon the completion of RequestGlobalDump() and |
| 79 // inject trace markers. | 82 // inject trace markers. |
| 80 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, | 83 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, |
| 81 uint64_t dump_guid, | 84 uint64_t dump_guid, |
| 82 bool success) { | 85 bool success) { |
| 83 TRACE_EVENT_NESTABLE_ASYNC_END1( | 86 char guid_str[20]; |
| 84 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", | 87 sprintf(guid_str, "0x%" PRIx64, dump_guid); |
| 85 TRACE_ID_MANGLE(dump_guid), "success", success); | 88 TRACE_EVENT_NESTABLE_ASYNC_END2(MemoryDumpManager::kTraceCategory, |
| 89 "GlobalMemoryDump", TRACE_ID_LOCAL(dump_guid), |
| 90 "dump_guid", TRACE_STR_COPY(guid_str), |
| 91 "success", success); |
| 86 | 92 |
| 87 if (!wrapped_callback.is_null()) { | 93 if (!wrapped_callback.is_null()) { |
| 88 wrapped_callback.Run(dump_guid, success); | 94 wrapped_callback.Run(dump_guid, success); |
| 89 wrapped_callback.Reset(); | 95 wrapped_callback.Reset(); |
| 90 } | 96 } |
| 91 } | 97 } |
| 92 | 98 |
| 93 // Proxy class which wraps a ConvertableToTraceFormat owned by the | 99 // Proxy class which wraps a ConvertableToTraceFormat owned by the |
| 94 // |session_state| into a proxy object that can be added to the trace event log. | 100 // |session_state| into a proxy object that can be added to the trace event log. |
| 95 // This is to solve the problem that the MemoryDumpSessionState is refcounted | 101 // This is to solve the problem that the MemoryDumpSessionState is refcounted |
| (...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 callback.Run(0u /* guid */, false /* success */); | 455 callback.Run(0u /* guid */, false /* success */); |
| 450 return; | 456 return; |
| 451 } | 457 } |
| 452 | 458 |
| 453 const uint64_t guid = | 459 const uint64_t guid = |
| 454 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 460 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
| 455 | 461 |
| 456 // Creates an async event to keep track of the global dump evolution. | 462 // Creates an async event to keep track of the global dump evolution. |
| 457 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 463 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
| 458 // the real |callback| provided by the caller. | 464 // the real |callback| provided by the caller. |
| 459 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "GlobalMemoryDump", | 465 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
| 460 TRACE_ID_MANGLE(guid)); | 466 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", |
| 467 MemoryDumpTypeToString(dump_type), "level_of_detail", |
| 468 MemoryDumpLevelOfDetailToString(level_of_detail)); |
| 461 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); | 469 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); |
| 462 | 470 |
| 463 // Technically there is no need to grab the |lock_| here as the delegate is | 471 // Technically there is no need to grab the |lock_| here as the delegate is |
| 464 // long-lived and can only be set by Initialize(), which is locked and | 472 // long-lived and can only be set by Initialize(), which is locked and |
| 465 // necessarily happens before memory_tracing_enabled_ == true. | 473 // necessarily happens before memory_tracing_enabled_ == true. |
| 466 // Not taking the |lock_|, though, is lakely make TSan barf and, at this point | 474 // Not taking the |lock_|, though, is lakely make TSan barf and, at this point |
| 467 // (memory-infra is enabled) we're not in the fast-path anymore. | 475 // (memory-infra is enabled) we're not in the fast-path anymore. |
| 468 MemoryDumpManagerDelegate* delegate; | 476 MemoryDumpManagerDelegate* delegate; |
| 469 { | 477 { |
| 470 AutoLock lock(lock_); | 478 AutoLock lock(lock_); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 489 | 497 |
| 490 for (const auto& info : dump_providers_) { | 498 for (const auto& info : dump_providers_) { |
| 491 if (info->dump_provider == provider) | 499 if (info->dump_provider == provider) |
| 492 return true; | 500 return true; |
| 493 } | 501 } |
| 494 return false; | 502 return false; |
| 495 } | 503 } |
| 496 | 504 |
| 497 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 505 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, |
| 498 const MemoryDumpCallback& callback) { | 506 const MemoryDumpCallback& callback) { |
| 499 TRACE_EVENT_NESTABLE_ASYNC_BEGIN0(kTraceCategory, "ProcessMemoryDump", | 507 char guid_str[20]; |
| 500 TRACE_ID_MANGLE(args.dump_guid)); | 508 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); |
| 509 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", |
| 510 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", |
| 511 TRACE_STR_COPY(guid_str)); |
| 501 | 512 |
| 502 // If argument filter is enabled then only background mode dumps should be | 513 // If argument filter is enabled then only background mode dumps should be |
| 503 // allowed. In case the trace config passed for background tracing session | 514 // allowed. In case the trace config passed for background tracing session |
| 504 // missed the allowed modes argument, it crashes here instead of creating | 515 // missed the allowed modes argument, it crashes here instead of creating |
| 505 // unexpected dumps. | 516 // unexpected dumps. |
| 506 if (TraceLog::GetInstance() | 517 if (TraceLog::GetInstance() |
| 507 ->GetCurrentTraceConfig() | 518 ->GetCurrentTraceConfig() |
| 508 .IsArgumentFilterEnabled()) { | 519 .IsArgumentFilterEnabled()) { |
| 509 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); | 520 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); |
| 510 } | 521 } |
| 511 | 522 |
| 512 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 523 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
| 513 { | 524 { |
| 514 AutoLock lock(lock_); | 525 AutoLock lock(lock_); |
| 515 | 526 |
| 516 // |dump_thread_| can be nullptr is tracing was disabled before reaching | 527 // |dump_thread_| can be nullptr is tracing was disabled before reaching |
| 517 // here. SetupNextMemoryDump() is robust enough to tolerate it and will | 528 // here. SetupNextMemoryDump() is robust enough to tolerate it and will |
| 518 // NACK the dump. | 529 // NACK the dump. |
| 519 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 530 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
| 520 args, dump_providers_, session_state_, callback, | 531 args, dump_providers_, session_state_, callback, |
| 521 dump_thread_ ? dump_thread_->task_runner() : nullptr)); | 532 dump_thread_ ? dump_thread_->task_runner() : nullptr)); |
| 522 | 533 |
| 523 // Safety check to prevent reaching here without calling RequestGlobalDump, | 534 // Safety check to prevent reaching here without calling RequestGlobalDump, |
| 524 // with disallowed modes. If |session_state_| is null then tracing is | 535 // with disallowed modes. If |session_state_| is null then tracing is |
| 525 // disabled. | 536 // disabled. |
| 526 CHECK(!session_state_ || | 537 CHECK(!session_state_ || |
| 527 session_state_->IsDumpModeAllowed(args.level_of_detail)); | 538 session_state_->IsDumpModeAllowed(args.level_of_detail)); |
| 528 } | 539 } |
| 529 | 540 |
| 530 TRACE_EVENT_WITH_FLOW0(kTraceCategory, "MemoryDumpManager::CreateProcessDump", | |
| 531 TRACE_ID_MANGLE(args.dump_guid), | |
| 532 TRACE_EVENT_FLAG_FLOW_OUT); | |
| 533 | |
| 534 // Start the process dump. This involves task runner hops as specified by the | 541 // Start the process dump. This involves task runner hops as specified by the |
| 535 // MemoryDumpProvider(s) in RegisterDumpProvider()). | 542 // MemoryDumpProvider(s) in RegisterDumpProvider()). |
| 536 SetupNextMemoryDump(std::move(pmd_async_state)); | 543 SetupNextMemoryDump(std::move(pmd_async_state)); |
| 537 } | 544 } |
| 538 | 545 |
| 539 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A | 546 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A |
| 540 // PostTask is always required for a generic SequencedTaskRunner to ensure that | 547 // PostTask is always required for a generic SequencedTaskRunner to ensure that |
| 541 // no other task is running on it concurrently. SetupNextMemoryDump() and | 548 // no other task is running on it concurrently. SetupNextMemoryDump() and |
| 542 // InvokeOnMemoryDump() are called alternatively which linearizes the dump | 549 // InvokeOnMemoryDump() are called alternatively which linearizes the dump |
| 543 // provider's OnMemoryDump invocations. | 550 // provider's OnMemoryDump invocations. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 667 mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) { | 674 mdpinfo->consecutive_failures >= kMaxConsecutiveFailuresCount) { |
| 668 mdpinfo->disabled = true; | 675 mdpinfo->disabled = true; |
| 669 LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name | 676 LOG(ERROR) << "Disabling MemoryDumpProvider \"" << mdpinfo->name |
| 670 << "\". Dump failed multiple times consecutively."; | 677 << "\". Dump failed multiple times consecutively."; |
| 671 } | 678 } |
| 672 should_dump = !mdpinfo->disabled; | 679 should_dump = !mdpinfo->disabled; |
| 673 } // AutoLock lock(lock_); | 680 } // AutoLock lock(lock_); |
| 674 | 681 |
| 675 if (should_dump) { | 682 if (should_dump) { |
| 676 // Invoke the dump provider. | 683 // Invoke the dump provider. |
| 677 TRACE_EVENT_WITH_FLOW1(kTraceCategory, | 684 TRACE_EVENT1(kTraceCategory, "MemoryDumpManager::InvokeOnMemoryDump", |
| 678 "MemoryDumpManager::InvokeOnMemoryDump", | 685 "dump_provider.name", mdpinfo->name); |
| 679 TRACE_ID_MANGLE(pmd_async_state->req_args.dump_guid), | |
| 680 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, | |
| 681 "dump_provider.name", mdpinfo->name); | |
| 682 | 686 |
| 683 // A stack allocated string with dump provider name is useful to debug | 687 // A stack allocated string with dump provider name is useful to debug |
| 684 // crashes while invoking dump after a |dump_provider| is not unregistered | 688 // crashes while invoking dump after a |dump_provider| is not unregistered |
| 685 // in safe way. | 689 // in safe way. |
| 686 // TODO(ssid): Remove this after fixing crbug.com/643438. | 690 // TODO(ssid): Remove this after fixing crbug.com/643438. |
| 687 char provider_name_for_debugging[16]; | 691 char provider_name_for_debugging[16]; |
| 688 strncpy(provider_name_for_debugging, mdpinfo->name, | 692 strncpy(provider_name_for_debugging, mdpinfo->name, |
| 689 sizeof(provider_name_for_debugging) - 1); | 693 sizeof(provider_name_for_debugging) - 1); |
| 690 provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0'; | 694 provider_name_for_debugging[sizeof(provider_name_for_debugging) - 1] = '\0'; |
| 691 base::debug::Alias(provider_name_for_debugging); | 695 base::debug::Alias(provider_name_for_debugging); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 737 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; | 741 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; |
| 738 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { | 742 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { |
| 739 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 743 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
| 740 pmd_async_state->callback_task_runner; | 744 pmd_async_state->callback_task_runner; |
| 741 callback_task_runner->PostTask( | 745 callback_task_runner->PostTask( |
| 742 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 746 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
| 743 Passed(&pmd_async_state))); | 747 Passed(&pmd_async_state))); |
| 744 return; | 748 return; |
| 745 } | 749 } |
| 746 | 750 |
| 747 TRACE_EVENT_WITH_FLOW0(kTraceCategory, | 751 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); |
| 748 "MemoryDumpManager::FinalizeDumpAndAddToTrace", | |
| 749 TRACE_ID_MANGLE(dump_guid), TRACE_EVENT_FLAG_FLOW_IN); | |
| 750 | 752 |
| 751 for (const auto& kv : pmd_async_state->process_dumps) { | 753 for (const auto& kv : pmd_async_state->process_dumps) { |
| 752 ProcessId pid = kv.first; // kNullProcessId for the current process. | 754 ProcessId pid = kv.first; // kNullProcessId for the current process. |
| 753 ProcessMemoryDump* process_memory_dump = kv.second.get(); | 755 ProcessMemoryDump* process_memory_dump = kv.second.get(); |
| 754 std::unique_ptr<TracedValue> traced_value(new TracedValue); | 756 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
| 755 process_memory_dump->AsValueInto(traced_value.get()); | 757 process_memory_dump->AsValueInto(traced_value.get()); |
| 756 traced_value->SetString("level_of_detail", | 758 traced_value->SetString("level_of_detail", |
| 757 MemoryDumpLevelOfDetailToString( | 759 MemoryDumpLevelOfDetailToString( |
| 758 pmd_async_state->req_args.level_of_detail)); | 760 pmd_async_state->req_args.level_of_detail)); |
| 759 const char* const event_name = | 761 const char* const event_name = |
| (...skipping 17 matching lines...) Expand all Loading... |
| 777 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" | 779 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" |
| 778 << " the dump was completed"; | 780 << " the dump was completed"; |
| 779 } | 781 } |
| 780 | 782 |
| 781 if (!pmd_async_state->callback.is_null()) { | 783 if (!pmd_async_state->callback.is_null()) { |
| 782 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful); | 784 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful); |
| 783 pmd_async_state->callback.Reset(); | 785 pmd_async_state->callback.Reset(); |
| 784 } | 786 } |
| 785 | 787 |
| 786 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 788 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
| 787 TRACE_ID_MANGLE(dump_guid)); | 789 TRACE_ID_LOCAL(dump_guid)); |
| 788 } | 790 } |
| 789 | 791 |
| 790 void MemoryDumpManager::OnTraceLogEnabled() { | 792 void MemoryDumpManager::OnTraceLogEnabled() { |
| 791 bool enabled; | 793 bool enabled; |
| 792 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); | 794 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); |
| 793 if (!enabled) | 795 if (!enabled) |
| 794 return; | 796 return; |
| 795 | 797 |
| 796 // Initialize the TraceLog for the current thread. This is to avoid that the | 798 // Initialize the TraceLog for the current thread. This is to avoid that the |
| 797 // TraceLog memory dump provider is registered lazily in the PostTask() below | 799 // TraceLog memory dump provider is registered lazily in the PostTask() below |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 if (iter == process_dumps.end()) { | 978 if (iter == process_dumps.end()) { |
| 977 std::unique_ptr<ProcessMemoryDump> new_pmd( | 979 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 978 new ProcessMemoryDump(session_state, dump_args)); | 980 new ProcessMemoryDump(session_state, dump_args)); |
| 979 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 981 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 980 } | 982 } |
| 981 return iter->second.get(); | 983 return iter->second.get(); |
| 982 } | 984 } |
| 983 | 985 |
| 984 } // namespace trace_event | 986 } // namespace trace_event |
| 985 } // namespace base | 987 } // namespace base |
| OLD | NEW |