summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao2018-07-30 20:51:55 -0500
committerJosh Gao2018-07-31 17:56:31 -0500
commit95af641bd65f6f02318ebc66bf5faaeb370108c8 (patch)
treea376f5c4463bc5e4bc5da1ceedf47b2064e0811a
parent190624301755d366ccc464b2223eeeec5c7ccd32 (diff)
downloadplatform-system-core-95af641bd65f6f02318ebc66bf5faaeb370108c8.tar.gz
platform-system-core-95af641bd65f6f02318ebc66bf5faaeb370108c8.tar.xz
platform-system-core-95af641bd65f6f02318ebc66bf5faaeb370108c8.zip
adb: don't pass time_point::max to condition_variable::wait_until.
libstdc++ implements wait_until by calculating the offset between its default clock and the clock that it's given by calling now() on each and subtracting, and then adds that offset to the time_point argument. When time_point::max is used, this overflows, resulting in the reconnection thread spinning. Test: wine adb.exe server nodaemon Change-Id: Ife58f0aad14bc44c0804483d3ff2351c28b3d576
-rw-r--r--adb/transport.cpp36
1 files changed, 24 insertions, 12 deletions
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 793c283fc..b08c7f9bb 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -102,7 +102,7 @@ class ReconnectHandler {
102 // Tracks a reconnection attempt. 102 // Tracks a reconnection attempt.
103 struct ReconnectAttempt { 103 struct ReconnectAttempt {
104 atransport* transport; 104 atransport* transport;
105 std::chrono::system_clock::time_point deadline; 105 std::chrono::steady_clock::time_point reconnect_time;
106 size_t attempts_left; 106 size_t attempts_left;
107 }; 107 };
108 108
@@ -149,8 +149,8 @@ void ReconnectHandler::TrackTransport(atransport* transport) {
149 std::lock_guard<std::mutex> lock(reconnect_mutex_); 149 std::lock_guard<std::mutex> lock(reconnect_mutex_);
150 if (!running_) return; 150 if (!running_) return;
151 reconnect_queue_.emplace(ReconnectAttempt{ 151 reconnect_queue_.emplace(ReconnectAttempt{
152 transport, std::chrono::system_clock::now() + ReconnectHandler::kDefaultTimeout, 152 transport, std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
153 ReconnectHandler::kMaxAttempts}); 153 ReconnectHandler::kMaxAttempts});
154 } 154 }
155 reconnect_cv_.notify_one(); 155 reconnect_cv_.notify_one();
156} 156}
@@ -162,14 +162,26 @@ void ReconnectHandler::Run() {
162 std::unique_lock<std::mutex> lock(reconnect_mutex_); 162 std::unique_lock<std::mutex> lock(reconnect_mutex_);
163 ScopedAssumeLocked assume_lock(reconnect_mutex_); 163 ScopedAssumeLocked assume_lock(reconnect_mutex_);
164 164
165 auto deadline = std::chrono::time_point<std::chrono::system_clock>::max(); 165 if (!reconnect_queue_.empty()) {
166 if (!reconnect_queue_.empty()) deadline = reconnect_queue_.front().deadline; 166 // FIXME: libstdc++ (used on Windows) implements condition_variable with
167 reconnect_cv_.wait_until(lock, deadline, [&]() REQUIRES(reconnect_mutex_) { 167 // system_clock as its clock, so we're probably hosed if the clock changes,
168 return !running_ || 168 // even if we use steady_clock throughout. This problem goes away once we
169 (!reconnect_queue_.empty() && reconnect_queue_.front().deadline < deadline); 169 // switch to libc++.
170 }); 170 reconnect_cv_.wait_until(lock, reconnect_queue_.front().reconnect_time);
171 } else {
172 reconnect_cv_.wait(lock);
173 }
171 174
172 if (!running_) return; 175 if (!running_) return;
176 if (reconnect_queue_.empty()) continue;
177
178 // Go back to sleep in case |reconnect_cv_| woke up spuriously and we still
179 // have more time to wait for the current attempt.
180 auto now = std::chrono::steady_clock::now();
181 if (reconnect_queue_.front().reconnect_time > now) {
182 continue;
183 }
184
173 attempt = reconnect_queue_.front(); 185 attempt = reconnect_queue_.front();
174 reconnect_queue_.pop(); 186 reconnect_queue_.pop();
175 if (attempt.transport->kicked()) { 187 if (attempt.transport->kicked()) {
@@ -191,9 +203,9 @@ void ReconnectHandler::Run() {
191 203
192 std::lock_guard<std::mutex> lock(reconnect_mutex_); 204 std::lock_guard<std::mutex> lock(reconnect_mutex_);
193 reconnect_queue_.emplace(ReconnectAttempt{ 205 reconnect_queue_.emplace(ReconnectAttempt{
194 attempt.transport, 206 attempt.transport,
195 std::chrono::system_clock::now() + ReconnectHandler::kDefaultTimeout, 207 std::chrono::steady_clock::now() + ReconnectHandler::kDefaultTimeout,
196 attempt.attempts_left - 1}); 208 attempt.attempts_left - 1});
197 continue; 209 continue;
198 } 210 }
199 211