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 |