diff options
author | Josh Gao | 2018-07-30 20:51:55 -0500 |
---|---|---|
committer | Josh Gao | 2018-07-31 17:56:31 -0500 |
commit | 95af641bd65f6f02318ebc66bf5faaeb370108c8 (patch) | |
tree | a376f5c4463bc5e4bc5da1ceedf47b2064e0811a | |
parent | 190624301755d366ccc464b2223eeeec5c7ccd32 (diff) | |
download | platform-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.cpp | 36 |
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 | ||