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 <algorithm> | 6 #include <algorithm> |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 TracingController* TracingController::GetInstance() { | 192 TracingController* TracingController::GetInstance() { |
193 return TracingControllerImpl::GetInstance(); | 193 return TracingControllerImpl::GetInstance(); |
194 } | 194 } |
195 | 195 |
196 TracingControllerImpl::TracingControllerImpl() | 196 TracingControllerImpl::TracingControllerImpl() |
197 : pending_start_tracing_ack_count_(0), | 197 : pending_start_tracing_ack_count_(0), |
198 pending_stop_tracing_ack_count_(0), | 198 pending_stop_tracing_ack_count_(0), |
199 pending_trace_log_status_ack_count_(0), | 199 pending_trace_log_status_ack_count_(0), |
200 maximum_trace_buffer_usage_(0), | 200 maximum_trace_buffer_usage_(0), |
201 approximate_event_count_(0), | 201 approximate_event_count_(0), |
202 pending_memory_dump_ack_count_(0), | |
203 failed_memory_dump_count_(0), | |
204 pending_clock_sync_ack_count_(0), | 202 pending_clock_sync_ack_count_(0), |
205 is_tracing_(false) { | 203 is_tracing_(false) { |
206 base::trace_event::MemoryDumpManager::GetInstance()->Initialize( | |
207 this /* delegate */, true /* is_coordinator */); | |
208 | |
209 // Deliberately leaked, like this class. | 204 // Deliberately leaked, like this class. |
210 base::FileTracing::SetProvider(new FileTracingProviderImpl); | 205 base::FileTracing::SetProvider(new FileTracingProviderImpl); |
211 } | 206 } |
212 | 207 |
213 TracingControllerImpl::~TracingControllerImpl() { | 208 TracingControllerImpl::~TracingControllerImpl() { |
214 // This is a Leaky instance. | 209 // This is a Leaky instance. |
215 NOTREACHED(); | 210 NOTREACHED(); |
216 } | 211 } |
217 | 212 |
218 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 213 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 pending_trace_log_status_filters_.find(trace_message_filter); | 536 pending_trace_log_status_filters_.find(trace_message_filter); |
542 if (it != pending_trace_log_status_filters_.end()) { | 537 if (it != pending_trace_log_status_filters_.end()) { |
543 BrowserThread::PostTask( | 538 BrowserThread::PostTask( |
544 BrowserThread::UI, FROM_HERE, | 539 BrowserThread::UI, FROM_HERE, |
545 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | 540 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, |
546 base::Unretained(this), | 541 base::Unretained(this), |
547 base::RetainedRef(trace_message_filter), | 542 base::RetainedRef(trace_message_filter), |
548 base::trace_event::TraceLogStatus())); | 543 base::trace_event::TraceLogStatus())); |
549 } | 544 } |
550 } | 545 } |
551 if (pending_memory_dump_ack_count_ > 0) { | |
552 DCHECK(!queued_memory_dump_requests_.empty()); | |
553 TraceMessageFilterSet::const_iterator it = | |
554 pending_memory_dump_filters_.find(trace_message_filter); | |
555 if (it != pending_memory_dump_filters_.end()) { | |
556 BrowserThread::PostTask( | |
557 BrowserThread::UI, FROM_HERE, | |
558 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse, | |
559 base::Unretained(this), | |
560 base::RetainedRef(trace_message_filter), | |
561 queued_memory_dump_requests_.front().args.dump_guid, | |
562 false /* success */)); | |
563 } | |
564 } | |
565 trace_message_filters_.erase(trace_message_filter); | 546 trace_message_filters_.erase(trace_message_filter); |
566 } | 547 } |
567 | 548 |
568 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) { | 549 void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) { |
569 #if defined(OS_CHROMEOS) | 550 #if defined(OS_CHROMEOS) |
570 auto* debug_daemon = | 551 auto* debug_daemon = |
571 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | 552 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); |
572 if (agent_name == debug_daemon->GetTracingAgentName()) { | 553 if (agent_name == debug_daemon->GetTracingAgentName()) { |
573 additional_tracing_agents_.push_back(debug_daemon); | 554 additional_tracing_agents_.push_back(debug_daemon); |
574 debug_daemon->SetStopAgentTracingTaskRunner( | 555 debug_daemon->SetStopAgentTracingTaskRunner( |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); | 889 for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd(); |
909 it.Advance()) { | 890 it.Advance()) { |
910 if (filter.Run(it.key())) | 891 if (filter.Run(it.key())) |
911 filtered_metadata->Set(it.key(), it.value().DeepCopy()); | 892 filtered_metadata->Set(it.key(), it.value().DeepCopy()); |
912 else | 893 else |
913 filtered_metadata->SetString(it.key(), "__stripped__"); | 894 filtered_metadata->SetString(it.key(), "__stripped__"); |
914 } | 895 } |
915 sink->AddMetadata(std::move(filtered_metadata)); | 896 sink->AddMetadata(std::move(filtered_metadata)); |
916 } | 897 } |
917 | 898 |
918 void TracingControllerImpl::RequestGlobalMemoryDump( | |
919 const base::trace_event::MemoryDumpRequestArgs& args, | |
920 const base::trace_event::MemoryDumpCallback& callback) { | |
921 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
922 BrowserThread::PostTask( | |
923 BrowserThread::UI, FROM_HERE, | |
924 base::Bind(&TracingControllerImpl::RequestGlobalMemoryDump, | |
925 base::Unretained(this), args, callback)); | |
926 return; | |
927 } | |
928 | |
929 bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty(); | |
930 | |
931 // If this is a periodic memory dump request and there already is another | |
932 // request in the queue with the same level of detail, there's no point in | |
933 // enqueuing this request. | |
934 if (another_dump_already_in_progress && | |
935 args.dump_type == base::trace_event::MemoryDumpType::PERIODIC_INTERVAL) { | |
936 for (const auto& request : queued_memory_dump_requests_) { | |
937 if (request.args.level_of_detail == args.level_of_detail) { | |
938 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" | |
939 << base::trace_event::MemoryDumpTypeToString(args.dump_type) | |
940 << ") skipped because another dump request with the same " | |
941 "level of detail (" | |
942 << base::trace_event::MemoryDumpLevelOfDetailToString( | |
943 args.level_of_detail) | |
944 << ") is already in the queue"; | |
945 if (!callback.is_null()) | |
946 callback.Run(args.dump_guid, false /* success */); | |
947 return; | |
948 } | |
949 } | |
950 } | |
951 | |
952 queued_memory_dump_requests_.emplace_back(args, callback); | |
953 | |
954 // If another dump is already in progress, this dump will automatically be | |
955 // scheduled when the other dump finishes. | |
956 if (another_dump_already_in_progress) | |
957 return; | |
958 | |
959 PerformNextQueuedGlobalMemoryDump(); | |
960 } | |
961 | |
962 void TracingControllerImpl::PerformNextQueuedGlobalMemoryDump() { | |
963 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
964 DCHECK(!queued_memory_dump_requests_.empty()); | |
965 const base::trace_event::MemoryDumpRequestArgs& args = | |
966 queued_memory_dump_requests_.front().args; | |
967 | |
968 // Count myself (local trace) in pending_memory_dump_ack_count_, acked by | |
969 // OnBrowserProcessMemoryDumpDone(). | |
970 pending_memory_dump_ack_count_ = trace_message_filters_.size() + 1; | |
971 pending_memory_dump_filters_.clear(); | |
972 failed_memory_dump_count_ = 0; | |
973 | |
974 MemoryDumpManagerDelegate::CreateProcessDump( | |
975 args, base::Bind(&TracingControllerImpl::OnBrowserProcessMemoryDumpDone, | |
976 base::Unretained(this))); | |
977 | |
978 // If there are no child processes we are just done. | |
979 if (pending_memory_dump_ack_count_ == 1) | |
980 return; | |
981 | |
982 pending_memory_dump_filters_ = trace_message_filters_; | |
983 | |
984 for (const scoped_refptr<TraceMessageFilter>& tmf : trace_message_filters_) | |
985 tmf->SendProcessMemoryDumpRequest(args); | |
986 } | |
987 | |
988 TracingControllerImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest( | |
989 const base::trace_event::MemoryDumpRequestArgs& args, | |
990 const base::trace_event::MemoryDumpCallback& callback) | |
991 : args(args), callback(callback) {} | |
992 | |
993 TracingControllerImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {} | |
994 | |
995 uint64_t TracingControllerImpl::GetTracingProcessId() const { | |
996 return ChildProcessHost::kBrowserTracingProcessId; | |
997 } | |
998 | |
999 void TracingControllerImpl::AddTraceMessageFilterObserver( | 899 void TracingControllerImpl::AddTraceMessageFilterObserver( |
1000 TraceMessageFilterObserver* observer) { | 900 TraceMessageFilterObserver* observer) { |
1001 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 901 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1002 trace_message_filter_observers_.AddObserver(observer); | 902 trace_message_filter_observers_.AddObserver(observer); |
1003 | 903 |
1004 for (auto& filter : trace_message_filters_) | 904 for (auto& filter : trace_message_filters_) |
1005 observer->OnTraceMessageFilterAdded(filter.get()); | 905 observer->OnTraceMessageFilterAdded(filter.get()); |
1006 } | 906 } |
1007 | 907 |
1008 void TracingControllerImpl::RemoveTraceMessageFilterObserver( | 908 void TracingControllerImpl::RemoveTraceMessageFilterObserver( |
1009 TraceMessageFilterObserver* observer) { | 909 TraceMessageFilterObserver* observer) { |
1010 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 910 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
1011 trace_message_filter_observers_.RemoveObserver(observer); | 911 trace_message_filter_observers_.RemoveObserver(observer); |
1012 | 912 |
1013 for (auto& filter : trace_message_filters_) | 913 for (auto& filter : trace_message_filters_) |
1014 observer->OnTraceMessageFilterRemoved(filter.get()); | 914 observer->OnTraceMessageFilterRemoved(filter.get()); |
1015 } | 915 } |
1016 | 916 |
1017 void TracingControllerImpl::OnProcessMemoryDumpResponse( | |
1018 TraceMessageFilter* trace_message_filter, | |
1019 uint64_t dump_guid, | |
1020 bool success) { | |
1021 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
1022 BrowserThread::PostTask( | |
1023 BrowserThread::UI, FROM_HERE, | |
1024 base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse, | |
1025 base::Unretained(this), | |
1026 base::RetainedRef(trace_message_filter), dump_guid, | |
1027 success)); | |
1028 return; | |
1029 } | |
1030 | |
1031 TraceMessageFilterSet::iterator it = | |
1032 pending_memory_dump_filters_.find(trace_message_filter); | |
1033 | |
1034 DCHECK(!queued_memory_dump_requests_.empty()); | |
1035 if (queued_memory_dump_requests_.front().args.dump_guid != dump_guid || | |
1036 it == pending_memory_dump_filters_.end()) { | |
1037 DLOG(WARNING) << "Received unexpected memory dump response: " << dump_guid; | |
1038 return; | |
1039 } | |
1040 | |
1041 DCHECK_GT(pending_memory_dump_ack_count_, 0); | |
1042 --pending_memory_dump_ack_count_; | |
1043 pending_memory_dump_filters_.erase(it); | |
1044 if (!success) { | |
1045 ++failed_memory_dump_count_; | |
1046 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix | |
1047 << " failed because of NACK from child " | |
1048 << trace_message_filter->peer_pid(); | |
1049 } | |
1050 FinalizeGlobalMemoryDumpIfAllProcessesReplied(); | |
1051 } | |
1052 | |
1053 void TracingControllerImpl::OnBrowserProcessMemoryDumpDone(uint64_t dump_guid, | |
1054 bool success) { | |
1055 DCHECK_GT(pending_memory_dump_ack_count_, 0); | |
1056 --pending_memory_dump_ack_count_; | |
1057 if (!success) { | |
1058 ++failed_memory_dump_count_; | |
1059 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix | |
1060 << " aborted on the current process"; | |
1061 } | |
1062 FinalizeGlobalMemoryDumpIfAllProcessesReplied(); | |
1063 } | |
1064 | |
1065 void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() { | |
1066 if (pending_memory_dump_ack_count_ > 0) | |
1067 return; | |
1068 | |
1069 DCHECK(!queued_memory_dump_requests_.empty()); | |
1070 { | |
1071 const auto& callback = queued_memory_dump_requests_.front().callback; | |
1072 if (!callback.is_null()) { | |
1073 const bool global_success = failed_memory_dump_count_ == 0; | |
1074 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, | |
1075 global_success); | |
1076 } | |
1077 } | |
1078 queued_memory_dump_requests_.pop_front(); | |
1079 | |
1080 // Schedule the next queued dump (if applicable). | |
1081 if (!queued_memory_dump_requests_.empty()) { | |
1082 BrowserThread::PostTask( | |
1083 BrowserThread::UI, FROM_HERE, | |
1084 base::Bind(&TracingControllerImpl::PerformNextQueuedGlobalMemoryDump, | |
1085 base::Unretained(this))); | |
1086 } | |
1087 } | |
1088 | |
1089 } // namespace content | 917 } // namespace content |
OLD | NEW |