| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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 #include "content/browser/tracing/tracing_controller_impl.h" | 4 #include "content/browser/tracing/tracing_controller_impl.h" |
| 5 | 5 |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/cpu.h" | 7 #include "base/cpu.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/guid.h" | 9 #include "base/guid.h" |
| 10 #include "base/json/string_escape.h" | 10 #include "base/json/string_escape.h" |
| 11 #include "base/macros.h" | 11 #include "base/macros.h" |
| 12 #include "base/memory/ref_counted_memory.h" | 12 #include "base/memory/ref_counted_memory.h" |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/sys_info.h" | 14 #include "base/sys_info.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 17 #include "base/trace_event/trace_event.h" | 17 #include "base/trace_event/trace_event.h" |
| 18 #include "build/build_config.h" | 18 #include "build/build_config.h" |
| 19 #include "components/tracing/common/process_metrics_memory_dump_provider.h" | |
| 20 #include "content/browser/tracing/file_tracing_provider_impl.h" | 19 #include "content/browser/tracing/file_tracing_provider_impl.h" |
| 21 #include "content/browser/tracing/trace_message_filter.h" | 20 #include "content/browser/tracing/trace_message_filter.h" |
| 22 #include "content/browser/tracing/tracing_ui.h" | 21 #include "content/browser/tracing/tracing_ui.h" |
| 23 #include "content/common/child_process_messages.h" | 22 #include "content/common/child_process_messages.h" |
| 24 #include "content/public/browser/browser_message_filter.h" | 23 #include "content/public/browser/browser_message_filter.h" |
| 25 #include "content/public/browser/content_browser_client.h" | 24 #include "content/public/browser/content_browser_client.h" |
| 26 #include "content/public/browser/gpu_data_manager.h" | 25 #include "content/public/browser/gpu_data_manager.h" |
| 27 #include "content/public/browser/tracing_delegate.h" | 26 #include "content/public/browser/tracing_delegate.h" |
| 28 #include "content/public/common/child_process_host.h" | 27 #include "content/public/common/child_process_host.h" |
| 29 #include "content/public/common/content_client.h" | 28 #include "content/public/common/content_client.h" |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 TracingController* TracingController::GetInstance() { | 184 TracingController* TracingController::GetInstance() { |
| 186 return TracingControllerImpl::GetInstance(); | 185 return TracingControllerImpl::GetInstance(); |
| 187 } | 186 } |
| 188 | 187 |
| 189 TracingControllerImpl::TracingControllerImpl() | 188 TracingControllerImpl::TracingControllerImpl() |
| 190 : pending_start_tracing_ack_count_(0), | 189 : pending_start_tracing_ack_count_(0), |
| 191 pending_stop_tracing_ack_count_(0), | 190 pending_stop_tracing_ack_count_(0), |
| 192 pending_trace_log_status_ack_count_(0), | 191 pending_trace_log_status_ack_count_(0), |
| 193 maximum_trace_buffer_usage_(0), | 192 maximum_trace_buffer_usage_(0), |
| 194 approximate_event_count_(0), | 193 approximate_event_count_(0), |
| 195 pending_memory_dump_ack_count_(0), | |
| 196 failed_memory_dump_count_(0), | |
| 197 pending_clock_sync_ack_count_(0), | 194 pending_clock_sync_ack_count_(0), |
| 198 is_tracing_(false) { | 195 is_tracing_(false) { |
| 199 base::trace_event::MemoryDumpManager::GetInstance()->Initialize( | |
| 200 this /* delegate */, true /* is_coordinator */); | |
| 201 | |
| 202 // Deliberately leaked, like this class. | 196 // Deliberately leaked, like this class. |
| 203 base::FileTracing::SetProvider(new FileTracingProviderImpl); | 197 base::FileTracing::SetProvider(new FileTracingProviderImpl); |
| 204 } | 198 } |
| 205 | 199 |
| 206 TracingControllerImpl::~TracingControllerImpl() { | 200 TracingControllerImpl::~TracingControllerImpl() { |
| 207 // This is a Leaky instance. | 201 // This is a Leaky instance. |
| 208 NOTREACHED(); | 202 NOTREACHED(); |
| 209 } | 203 } |
| 210 | 204 |
| 211 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 205 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 468 TraceMessageFilter* trace_message_filter) { | 462 TraceMessageFilter* trace_message_filter) { |
| 469 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 463 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 470 BrowserThread::PostTask( | 464 BrowserThread::PostTask( |
| 471 BrowserThread::UI, FROM_HERE, | 465 BrowserThread::UI, FROM_HERE, |
| 472 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, | 466 base::Bind(&TracingControllerImpl::AddTraceMessageFilter, |
| 473 base::Unretained(this), | 467 base::Unretained(this), |
| 474 base::RetainedRef(trace_message_filter))); | 468 base::RetainedRef(trace_message_filter))); |
| 475 return; | 469 return; |
| 476 } | 470 } |
| 477 | 471 |
| 478 #if defined(OS_LINUX) | |
| 479 // On Linux the browser process dumps process metrics for child process due to | |
| 480 // sandbox. | |
| 481 tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess( | |
| 482 trace_message_filter->peer_pid()); | |
| 483 #endif | |
| 484 | |
| 485 trace_message_filters_.insert(trace_message_filter); | 472 trace_message_filters_.insert(trace_message_filter); |
| 486 if (can_stop_tracing()) { | 473 if (can_stop_tracing()) { |
| 487 trace_message_filter->SendBeginTracing( | 474 trace_message_filter->SendBeginTracing( |
| 488 TraceLog::GetInstance()->GetCurrentTraceConfig()); | 475 TraceLog::GetInstance()->GetCurrentTraceConfig()); |
| 489 } | 476 } |
| 490 | 477 |
| 491 for (auto& observer : trace_message_filter_observers_) | 478 for (auto& observer : trace_message_filter_observers_) |
| 492 observer.OnTraceMessageFilterAdded(trace_message_filter); | 479 observer.OnTraceMessageFilterAdded(trace_message_filter); |
| 493 } | 480 } |
| 494 | 481 |
| 495 void TracingControllerImpl::RemoveTraceMessageFilter( | 482 void TracingControllerImpl::RemoveTraceMessageFilter( |
| 496 TraceMessageFilter* trace_message_filter) { | 483 TraceMessageFilter* trace_message_filter) { |
| 497 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 484 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 498 BrowserThread::PostTask( | 485 BrowserThread::PostTask( |
| 499 BrowserThread::UI, FROM_HERE, | 486 BrowserThread::UI, FROM_HERE, |
| 500 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, | 487 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, |
| 501 base::Unretained(this), | 488 base::Unretained(this), |
| 502 base::RetainedRef(trace_message_filter))); | 489 base::RetainedRef(trace_message_filter))); |
| 503 return; | 490 return; |
| 504 } | 491 } |
| 505 | 492 |
| 506 #if defined(OS_LINUX) | |
| 507 tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess( | |
| 508 trace_message_filter->peer_pid()); | |
| 509 #endif | |
| 510 | |
| 511 // If a filter is removed while a response from that filter is pending then | 493 // If a filter is removed while a response from that filter is pending then |
| 512 // simulate the response. Otherwise the response count will be wrong and the | 494 // simulate the response. Otherwise the response count will be wrong and the |
| 513 // completion callback will never be executed. | 495 // completion callback will never be executed. |
| 514 if (pending_stop_tracing_ack_count_ > 0) { | 496 if (pending_stop_tracing_ack_count_ > 0) { |
| 515 TraceMessageFilterSet::const_iterator it = | 497 TraceMessageFilterSet::const_iterator it = |
| 516 pending_stop_tracing_filters_.find(trace_message_filter); | 498 pending_stop_tracing_filters_.find(trace_message_filter); |
| 517 if (it != pending_stop_tracing_filters_.end()) { | 499 if (it != pending_stop_tracing_filters_.end()) { |
| 518 BrowserThread::PostTask( | 500 BrowserThread::PostTask( |
| 519 BrowserThread::UI, FROM_HERE, | 501 BrowserThread::UI, FROM_HERE, |
| 520 base::Bind(&TracingControllerImpl::OnStopTracingAcked, | 502 base::Bind(&TracingControllerImpl::OnStopTracingAcked, |
| 521 base::Unretained(this), | 503 base::Unretained(this), |
| 522 base::RetainedRef(trace_message_filter), | 504 base::RetainedRef(trace_message_filter), |
| 523 std::vector<std::string>())); | 505 std::vector<std::string>())); |
| 524 } | 506 } |
| 525 } | 507 } |
| 526 if (pending_trace_log_status_ack_count_ > 0) { | 508 if (pending_trace_log_status_ack_count_ > 0) { |
| 527 TraceMessageFilterSet::const_iterator it = | 509 TraceMessageFilterSet::const_iterator it = |
| 528 pending_trace_log_status_filters_.find(trace_message_filter); | 510 pending_trace_log_status_filters_.find(trace_message_filter); |
| 529 if (it != pending_trace_log_status_filters_.end()) { | 511 if (it != pending_trace_log_status_filters_.end()) { |
| 530 BrowserThread::PostTask( | 512 BrowserThread::PostTask( |
| 531 BrowserThread::UI, FROM_HERE, | 513 BrowserThread::UI, FROM_HERE, |
| 532 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | 514 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, |
| 533 base::Unretained(this), | 515 base::Unretained(this), |
| 534 base::RetainedRef(trace_message_filter), | 516 base::RetainedRef(trace_message_filter), |
| 535 base::trace_event::TraceLogStatus())); | 517 base::trace_event::TraceLogStatus())); |
| 536 } | 518 } |
| 537 } | 519 } |
| 538 if (pending_memory_dump_ack_count_ > 0) { | |
| 539 DCHECK(!queued_memory_dump_requests_.empty()); | |
| 540 TraceMessageFilterSet::const_iterator it = | |
| 541 pending_memory_dump_filters_.find(trace_message_filter); | |
| 542 if (it != pending_memory_dump_filters_.end()) { | |
| 543 BrowserThread::PostTask( | |
| 544 BrowserThread::UI, FROM_HERE, | |
| 545 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse, | |
| 546 base::Unretained(this), | |
| 547 base::RetainedRef(trace_message_filter), | |
| 548 queued_memory_dump_requests_.front().args.dump_guid, | |
| 549 false /* success */)); | |
| 550 } | |
| 551 } | |
| 552 trace_message_filters_.erase(trace_message_filter); | 520 trace_message_filters_.erase(trace_message_filter); |
| 553 } | 521 } |
| 554 | 522 |
| 555 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) { | 523 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) { |
| 556 #if defined(OS_CHROMEOS) | 524 #if defined(OS_CHROMEOS) |
| 557 auto* debug_daemon = | 525 auto* debug_daemon = |
| 558 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | 526 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); |
| 559 if (agent_name == debug_daemon->GetTracingAgentName()) { | 527 if (agent_name == debug_daemon->GetTracingAgentName()) { |
| 560 additional_tracing_agents_.push_back(debug_daemon); | 528 additional_tracing_agents_.push_back(debug_daemon); |
| 561 debug_daemon->SetStopAgentTracingTaskRunner( | 529 debug_daemon->SetStopAgentTracingTaskRunner( |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 888 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); | 856 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); |
| 889 it.Advance()) { | 857 it.Advance()) { |
| 890 if (filter.Run(it.key())) | 858 if (filter.Run(it.key())) |
| 891 filtered_metadata->Set(it.key(), it.value().DeepCopy()); | 859 filtered_metadata->Set(it.key(), it.value().DeepCopy()); |
| 892 else | 860 else |
| 893 filtered_metadata->SetString(it.key(), "__stripped__"); | 861 filtered_metadata->SetString(it.key(), "__stripped__"); |
| 894 } | 862 } |
| 895 sink->AddMetadata(std::move(filtered_metadata)); | 863 sink->AddMetadata(std::move(filtered_metadata)); |
| 896 } | 864 } |
| 897 | 865 |
| 898 void TracingControllerImpl::RequestGlobalMemoryDump( | |
| 899 const base::trace_event::MemoryDumpRequestArgs& args, | |
| 900 const base::trace_event::MemoryDumpCallback& callback) { | |
| 901 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 902 BrowserThread::PostTask( | |
| 903 BrowserThread::UI, FROM_HERE, | |
| 904 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump, | |
| 905 base::Unretained(this), args, callback)); | |
| 906 return; | |
| 907 } | |
| 908 | |
| 909 bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty(); | |
| 910 | |
| 911 // If this is a periodic memory dump request and there already is another | |
| 912 // request in the queue with the same level of detail, there's no point in | |
| 913 // enqueuing this request. | |
| 914 if (another_dump_already_in_progress && | |
| 915 args.dump_type == base::trace_event::MemoryDumpType::PERIODIC_INTERVAL) { | |
| 916 for (const auto& request : queued_memory_dump_requests_) { | |
| 917 if (request.args.level_of_detail == args.level_of_detail) { | |
| 918 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" | |
| 919 << base::trace_event::MemoryDumpTypeToString(args.dump_type) | |
| 920 << ") skipped because another dump request with the same " | |
| 921 "level of detail (" | |
| 922 << base::trace_event::MemoryDumpLevelOfDetailToString( | |
| 923 args.level_of_detail) | |
| 924 << ") is already in the queue"; | |
| 925 if (!callback.is_null()) | |
| 926 callback.Run(args.dump_guid, false /* success */); | |
| 927 return; | |
| 928 } | |
| 929 } | |
| 930 } | |
| 931 | |
| 932 queued_memory_dump_requests_.emplace_back(args, callback); | |
| 933 | |
| 934 // If another dump is already in progress, this dump will automatically be | |
| 935 // scheduled when the other dump finishes. | |
| 936 if (another_dump_already_in_progress) | |
| 937 return; | |
| 938 | |
| 939 PerformNextQueuedGlobalMemoryDump(); | |
| 940 } | |
| 941 | |
| 942 void TracingControllerImpl::PerformNextQueuedGlobalMemoryDump() { | |
| 943 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 944 DCHECK(!queued_memory_dump_requests_.empty()); | |
| 945 const base::trace_event::MemoryDumpRequestArgs& args = | |
| 946 queued_memory_dump_requests_.front().args; | |
| 947 | |
| 948 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by | |
| 949 // OnBrowserProcessMemoryDumpDone(). | |
| 950 pending_memory_dump_ack_count_ = trace_message_filters_.size() + 1; | |
| 951 pending_memory_dump_filters_.clear(); | |
| 952 failed_memory_dump_count_ = 0; | |
| 953 | |
| 954 MemoryDumpManagerDelegate::CreateProcessDump( | |
| 955 args, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone, | |
| 956 base::Unretained(this))); | |
| 957 | |
| 958 // If there are no child processes we are just done. | |
| 959 if (pending_memory_dump_ack_count_ == 1) | |
| 960 return; | |
| 961 | |
| 962 pending_memory_dump_filters_ = trace_message_filters_; | |
| 963 | |
| 964 for (const scoped_refptr<TraceMessageFilter>& tmf : trace_message_filters_) | |
| 965 tmf->SendProcessMemoryDumpRequest(args); | |
| 966 } | |
| 967 | |
| 968 TracingControllerImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest( | |
| 969 const base::trace_event::MemoryDumpRequestArgs& args, | |
| 970 const base::trace_event::MemoryDumpCallback& callback) | |
| 971 : args(args), callback(callback) {} | |
| 972 | |
| 973 TracingControllerImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {} | |
| 974 | |
| 975 uint64_t TracingControllerImpl::GetTracingProcessId() const { | |
| 976 return ChildProcessHost::kBrowserTracingProcessId; | |
| 977 } | |
| 978 | |
| 979 void TracingControllerImpl::AddTraceMessageFilterObserver( | 866 void TracingControllerImpl::AddTraceMessageFilterObserver( |
| 980 TraceMessageFilterObserver* observer) { | 867 TraceMessageFilterObserver* observer) { |
| 981 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 868 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 982 trace_message_filter_observers_.AddObserver(observer); | 869 trace_message_filter_observers_.AddObserver(observer); |
| 983 | 870 |
| 984 for (auto& filter : trace_message_filters_) | 871 for (auto& filter : trace_message_filters_) |
| 985 observer->OnTraceMessageFilterAdded(filter.get()); | 872 observer->OnTraceMessageFilterAdded(filter.get()); |
| 986 } | 873 } |
| 987 | 874 |
| 988 void TracingControllerImpl::RemoveTraceMessageFilterObserver( | 875 void TracingControllerImpl::RemoveTraceMessageFilterObserver( |
| 989 TraceMessageFilterObserver* observer) { | 876 TraceMessageFilterObserver* observer) { |
| 990 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 877 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 991 trace_message_filter_observers_.RemoveObserver(observer); | 878 trace_message_filter_observers_.RemoveObserver(observer); |
| 992 | 879 |
| 993 for (auto& filter : trace_message_filters_) | 880 for (auto& filter : trace_message_filters_) |
| 994 observer->OnTraceMessageFilterRemoved(filter.get()); | 881 observer->OnTraceMessageFilterRemoved(filter.get()); |
| 995 } | 882 } |
| 996 | 883 |
| 997 void TracingControllerImpl::OnProcessMemoryDumpResponse( | |
| 998 TraceMessageFilter* trace_message_filter, | |
| 999 uint64_t dump_guid, | |
| 1000 bool success) { | |
| 1001 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
| 1002 BrowserThread::PostTask( | |
| 1003 BrowserThread::UI, FROM_HERE, | |
| 1004 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse, | |
| 1005 base::Unretained(this), | |
| 1006 base::RetainedRef(trace_message_filter), dump_guid, | |
| 1007 success)); | |
| 1008 return; | |
| 1009 } | |
| 1010 | |
| 1011 TraceMessageFilterSet::iterator it = | |
| 1012 pending_memory_dump_filters_.find(trace_message_filter); | |
| 1013 | |
| 1014 DCHECK(!queued_memory_dump_requests_.empty()); | |
| 1015 if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid || | |
| 1016 it == pending_memory_dump_filters_.end()) { | |
| 1017 DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid; | |
| 1018 return; | |
| 1019 } | |
| 1020 | |
| 1021 DCHECK_GT(pending_memory_dump_ack_count_, 0); | |
| 1022 --pending_memory_dump_ack_count_; | |
| 1023 pending_memory_dump_filters_.erase(it); | |
| 1024 if (!success) { | |
| 1025 ++failed_memory_dump_count_; | |
| 1026 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix | |
| 1027 << " failed because of NACK from child " | |
| 1028 << trace_message_filter->peer_pid(); | |
| 1029 } | |
| 1030 FinalizeGlobalMemoryDumpIfAllProcessesReplied(); | |
| 1031 } | |
| 1032 | |
| 1033 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64_t dump_guid, | |
| 1034 bool success) { | |
| 1035 DCHECK_GT(pending_memory_dump_ack_count_, 0); | |
| 1036 --pending_memory_dump_ack_count_; | |
| 1037 if (!success) { | |
| 1038 ++failed_memory_dump_count_; | |
| 1039 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix | |
| 1040 << " aborted on the current process"; | |
| 1041 } | |
| 1042 FinalizeGlobalMemoryDumpIfAllProcessesReplied(); | |
| 1043 } | |
| 1044 | |
| 1045 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() { | |
| 1046 if (pending_memory_dump_ack_count_ > 0) | |
| 1047 return; | |
| 1048 | |
| 1049 DCHECK(!queued_memory_dump_requests_.empty()); | |
| 1050 { | |
| 1051 const auto& callback = queued_memory_dump_requests_.front().callback; | |
| 1052 if (!callback.is_null()) { | |
| 1053 const bool global_success = failed_memory_dump_count_ == 0; | |
| 1054 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, | |
| 1055 global_success); | |
| 1056 } | |
| 1057 } | |
| 1058 queued_memory_dump_requests_.pop_front(); | |
| 1059 | |
| 1060 // Schedule the next queued dump (if applicable). | |
| 1061 if (!queued_memory_dump_requests_.empty()) { | |
| 1062 BrowserThread::PostTask( | |
| 1063 BrowserThread::UI, FROM_HERE, | |
| 1064 base::Bind(&TracingControllerImpl::PerformNextQueuedGlobalMemoryDump, | |
| 1065 base::Unretained(this))); | |
| 1066 } | |
| 1067 } | |
| 1068 | |
| 1069 } // namespace content | 884 } // namespace content |
| OLD | NEW |