| 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 "services/tracing/service.h" | 5 #include "services/tracing/service.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/bind.h" | 12 #include "base/bind.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
| 16 #include "mojo/public/cpp/system/wait.h" |
| 16 #include "services/service_manager/public/cpp/interface_registry.h" | 17 #include "services/service_manager/public/cpp/interface_registry.h" |
| 17 | 18 |
| 18 namespace tracing { | 19 namespace tracing { |
| 19 | 20 |
| 20 Service::Service() : collector_binding_(this), tracing_active_(false) {} | 21 Service::Service() : collector_binding_(this), tracing_active_(false) {} |
| 21 Service::~Service() {} | 22 Service::~Service() {} |
| 22 | 23 |
| 23 bool Service::OnConnect(const service_manager::ServiceInfo& remote_info, | 24 bool Service::OnConnect(const service_manager::ServiceInfo& remote_info, |
| 24 service_manager::InterfaceRegistry* registry) { | 25 service_manager::InterfaceRegistry* registry) { |
| 25 registry->AddInterface<mojom::Factory>(this); | 26 registry->AddInterface<mojom::Factory>(this); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 | 88 |
| 88 tracing_active_ = false; | 89 tracing_active_ = false; |
| 89 provider_ptrs_.ForAllPtrs( | 90 provider_ptrs_.ForAllPtrs( |
| 90 [](mojom::Provider* controller) { controller->StopTracing(); }); | 91 [](mojom::Provider* controller) { controller->StopTracing(); }); |
| 91 | 92 |
| 92 // Sending the StopTracing message to registered controllers will request that | 93 // Sending the StopTracing message to registered controllers will request that |
| 93 // they send trace data back via the collector interface and, when they are | 94 // they send trace data back via the collector interface and, when they are |
| 94 // done, close the collector pipe. We don't know how long they will take. We | 95 // done, close the collector pipe. We don't know how long they will take. We |
| 95 // want to read all data that any collector might send until all collectors or | 96 // want to read all data that any collector might send until all collectors or |
| 96 // closed or an (arbitrary) deadline has passed. Since the bindings don't | 97 // closed or an (arbitrary) deadline has passed. Since the bindings don't |
| 97 // support this directly we do our own MojoWaitMany over the handles and read | 98 // support this directly we do our own WaitMany over the handles and read |
| 98 // individual messages until all are closed or our absolute deadline has | 99 // individual messages until all are closed or our absolute deadline has |
| 99 // elapsed. | 100 // elapsed. |
| 100 static const MojoDeadline kTimeToWaitMicros = 1000 * 1000; | 101 static const MojoDeadline kTimeToWaitMicros = 1000 * 1000; |
| 101 MojoTimeTicks end = MojoGetTimeTicksNow() + kTimeToWaitMicros; | 102 MojoTimeTicks end = MojoGetTimeTicksNow() + kTimeToWaitMicros; |
| 102 | 103 |
| 103 while (!recorder_impls_.empty()) { | 104 while (!recorder_impls_.empty()) { |
| 104 MojoTimeTicks now = MojoGetTimeTicksNow(); | 105 MojoTimeTicks now = MojoGetTimeTicksNow(); |
| 105 if (now >= end) // Timed out? | 106 if (now >= end) // Timed out? |
| 106 break; | 107 break; |
| 107 | 108 |
| 108 MojoDeadline mojo_deadline = end - now; | |
| 109 std::vector<mojo::Handle> handles; | 109 std::vector<mojo::Handle> handles; |
| 110 std::vector<MojoHandleSignals> signals; | 110 std::vector<MojoHandleSignals> signals; |
| 111 for (const auto& it : recorder_impls_) { | 111 for (const auto& it : recorder_impls_) { |
| 112 handles.push_back(it->RecorderHandle()); | 112 handles.push_back(it->RecorderHandle()); |
| 113 signals.push_back(MOJO_HANDLE_SIGNAL_READABLE | | 113 signals.push_back(MOJO_HANDLE_SIGNAL_READABLE | |
| 114 MOJO_HANDLE_SIGNAL_PEER_CLOSED); | 114 MOJO_HANDLE_SIGNAL_PEER_CLOSED); |
| 115 } | 115 } |
| 116 std::vector<MojoHandleSignalsState> signals_states(signals.size()); | 116 std::vector<MojoHandleSignalsState> signals_states(signals.size()); |
| 117 const mojo::WaitManyResult wait_many_result = | 117 size_t result_index; |
| 118 mojo::WaitMany(handles, signals, mojo_deadline, &signals_states); | 118 |
| 119 if (wait_many_result.result == MOJO_RESULT_DEADLINE_EXCEEDED) { | 119 // TODO(rockot): Use a timed wait here to avoid hanging forever in the case |
| 120 // Timed out waiting, nothing more to read. | 120 // of a misbehaving or unresponsive collector. |
| 121 LOG(WARNING) << "Timed out waiting for trace flush"; | 121 MojoResult rv = |
| 122 break; | 122 mojo::WaitMany(handles.data(), signals.data(), handles.size(), |
| 123 } | 123 &result_index, signals_states.data()); |
| 124 if (wait_many_result.IsIndexValid()) { | 124 if (rv == MOJO_RESULT_OK || rv == MOJO_RESULT_FAILED_PRECONDITION) { |
| 125 // Iterate backwards so we can remove closed pipes from |recorder_impls_| | 125 // Iterate backwards so we can remove closed pipes from |recorder_impls_| |
| 126 // without invalidating subsequent offsets. | 126 // without invalidating subsequent offsets. |
| 127 for (size_t i = signals_states.size(); i != 0; --i) { | 127 for (size_t i = signals_states.size(); i != 0; --i) { |
| 128 size_t index = i - 1; | 128 size_t index = i - 1; |
| 129 MojoHandleSignals satisfied = signals_states[index].satisfied_signals; | 129 MojoHandleSignals satisfied = signals_states[index].satisfied_signals; |
| 130 // To avoid dropping data, don't close unless there's no | 130 // To avoid dropping data, don't close unless there's no |
| 131 // readable signal. | 131 // readable signal. |
| 132 if (satisfied & MOJO_HANDLE_SIGNAL_READABLE) | 132 if (satisfied & MOJO_HANDLE_SIGNAL_READABLE) |
| 133 recorder_impls_[index]->TryRead(); | 133 recorder_impls_[index]->TryRead(); |
| 134 else if (satisfied & MOJO_HANDLE_SIGNAL_PEER_CLOSED) | 134 else if (satisfied & MOJO_HANDLE_SIGNAL_PEER_CLOSED) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 const GetStartupPerformanceTimesCallback& callback) { | 178 const GetStartupPerformanceTimesCallback& callback) { |
| 179 callback.Run(startup_performance_times_.Clone()); | 179 callback.Run(startup_performance_times_.Clone()); |
| 180 } | 180 } |
| 181 | 181 |
| 182 void Service::AllDataCollected() { | 182 void Service::AllDataCollected() { |
| 183 recorder_impls_.clear(); | 183 recorder_impls_.clear(); |
| 184 sink_.reset(); | 184 sink_.reset(); |
| 185 } | 185 } |
| 186 | 186 |
| 187 } // namespace tracing | 187 } // namespace tracing |
| OLD | NEW |