Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(60)

Side by Side Diff: google_apis/gcm/engine/connection_factory_impl.cc

Issue 980433003: [GCM] Fix crash during connection races (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | google_apis/gcm/engine/connection_factory_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 4
5 #include "google_apis/gcm/engine/connection_factory_impl.h" 5 #include "google_apis/gcm/engine/connection_factory_impl.h"
6 6
7 #include "base/message_loop/message_loop.h" 7 #include "base/message_loop/message_loop.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/metrics/sparse_histogram.h" 9 #include "base/metrics/sparse_histogram.h"
10 #include "google_apis/gcm/engine/connection_handler_impl.h" 10 #include "google_apis/gcm/engine/connection_handler_impl.h"
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
138 base::MessageLoop::current()->PostDelayedTask( 138 base::MessageLoop::current()->PostDelayedTask(
139 FROM_HERE, 139 FROM_HERE,
140 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff, 140 base::Bind(&ConnectionFactoryImpl::ConnectWithBackoff,
141 weak_ptr_factory_.GetWeakPtr()), 141 weak_ptr_factory_.GetWeakPtr()),
142 backoff_entry_->GetTimeUntilRelease()); 142 backoff_entry_->GetTimeUntilRelease());
143 return; 143 return;
144 } 144 }
145 145
146 DVLOG(1) << "Attempting connection to MCS endpoint."; 146 DVLOG(1) << "Attempting connection to MCS endpoint.";
147 waiting_for_backoff_ = false; 147 waiting_for_backoff_ = false;
148 // It's necessary to close the socket before attempting any new connection,
149 // otherwise it's possible to hit a use-after-free in the connection handler.
150 // crbug.com/462319
151 CloseSocket();
148 ConnectImpl(); 152 ConnectImpl();
149 } 153 }
150 154
151 bool ConnectionFactoryImpl::IsEndpointReachable() const { 155 bool ConnectionFactoryImpl::IsEndpointReachable() const {
152 return connection_handler_ && connection_handler_->CanSendMessage(); 156 return connection_handler_ && connection_handler_->CanSendMessage();
153 } 157 }
154 158
155 std::string ConnectionFactoryImpl::GetConnectionStateString() const { 159 std::string ConnectionFactoryImpl::GetConnectionStateString() const {
156 if (IsEndpointReachable()) 160 if (IsEndpointReachable())
157 return "CONNECTED"; 161 return "CONNECTED";
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 209
206 // Network changes get special treatment as they can trigger a one-off canary 210 // Network changes get special treatment as they can trigger a one-off canary
207 // request that bypasses backoff (but does nothing if a connection is in 211 // request that bypasses backoff (but does nothing if a connection is in
208 // progress). Other connection reset events can be ignored as a connection 212 // progress). Other connection reset events can be ignored as a connection
209 // is already awaiting backoff expiration. 213 // is already awaiting backoff expiration.
210 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) { 214 if (waiting_for_backoff_ && reason != NETWORK_CHANGE) {
211 DVLOG(1) << "Backoff expiration pending, ignoring reset."; 215 DVLOG(1) << "Backoff expiration pending, ignoring reset.";
212 return; 216 return;
213 } 217 }
214 218
215 if (logging_in_) { 219 if (reason == NETWORK_CHANGE) {
220 // Canary attempts bypass backoff without resetting it. These will have no
221 // effect if we're already in the process of connecting.
fgorski 2015/03/04 17:43:04 To confirm. There is no need to close socket here,
Nicolas Zea 2015/03/04 17:56:42 We do it on line 204 above.
222 ConnectImpl();
223 return;
224 } else if (logging_in_) {
216 // Failures prior to login completion just reuse the existing backoff entry. 225 // Failures prior to login completion just reuse the existing backoff entry.
217 logging_in_ = false; 226 logging_in_ = false;
218 backoff_entry_->InformOfRequest(false); 227 backoff_entry_->InformOfRequest(false);
219 } else if (reason == LOGIN_FAILURE || 228 } else if (reason == LOGIN_FAILURE ||
220 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) { 229 ShouldRestorePreviousBackoff(last_login_time_, NowTicks())) {
221 // Failures due to login, or within the reset window of a login, restore 230 // Failures due to login, or within the reset window of a login, restore
222 // the backoff entry that was saved off at login completion time. 231 // the backoff entry that was saved off at login completion time.
223 backoff_entry_.swap(previous_backoff_); 232 backoff_entry_.swap(previous_backoff_);
224 backoff_entry_->InformOfRequest(false); 233 backoff_entry_->InformOfRequest(false);
225 } else if (reason == NETWORK_CHANGE) {
226 ConnectImpl(); // Canary attempts bypass backoff without resetting it.
227 return;
228 } else { 234 } else {
229 // We shouldn't be in backoff in thise case. 235 // We shouldn't be in backoff in thise case.
230 DCHECK_EQ(0, backoff_entry_->failure_count()); 236 DCHECK_EQ(0, backoff_entry_->failure_count());
231 } 237 }
232 238
233 // At this point the last login time has been consumed or deemed irrelevant, 239 // At this point the last login time has been consumed or deemed irrelevant,
234 // reset it. 240 // reset it.
235 last_login_time_ = base::TimeTicks(); 241 last_login_time_ = base::TimeTicks();
236 242
237 Connect(); 243 Connect();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 net::IPEndPoint ip_endpoint; 286 net::IPEndPoint ip_endpoint;
281 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint); 287 int result = socket_handle_.socket()->GetPeerAddress(&ip_endpoint);
282 if (result != net::OK) 288 if (result != net::OK)
283 return net::IPEndPoint(); 289 return net::IPEndPoint();
284 290
285 return ip_endpoint; 291 return ip_endpoint;
286 } 292 }
287 293
288 void ConnectionFactoryImpl::ConnectImpl() { 294 void ConnectionFactoryImpl::ConnectImpl() {
289 DCHECK(!IsEndpointReachable()); 295 DCHECK(!IsEndpointReachable());
290 DCHECK(!socket_handle_.socket()); 296 // TODO(zea): Make this a dcheck again. crbug.com/462319
297 CHECK(!socket_handle_.socket());
291 298
292 // TODO(zea): if the network is offline, don't attempt to connect. 299 // TODO(zea): if the network is offline, don't attempt to connect.
293 // See crbug.com/396687 300 // See crbug.com/396687
294 301
295 connecting_ = true; 302 connecting_ = true;
296 GURL current_endpoint = GetCurrentEndpoint(); 303 GURL current_endpoint = GetCurrentEndpoint();
297 recorder_->RecordConnectionInitiated(current_endpoint.host()); 304 recorder_->RecordConnectionInitiated(current_endpoint.host());
298 RebuildNetworkSessionAuthCache(); 305 RebuildNetworkSessionAuthCache();
299 int status = gcm_network_session_->proxy_service()->ResolveProxy( 306 int status = gcm_network_session_->proxy_service()->ResolveProxy(
300 current_endpoint, 307 current_endpoint,
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 569
563 void ConnectionFactoryImpl::RebuildNetworkSessionAuthCache() { 570 void ConnectionFactoryImpl::RebuildNetworkSessionAuthCache() {
564 if (!http_network_session_.get() || !http_network_session_->http_auth_cache()) 571 if (!http_network_session_.get() || !http_network_session_->http_auth_cache())
565 return; 572 return;
566 573
567 gcm_network_session_->http_auth_cache()->UpdateAllFrom( 574 gcm_network_session_->http_auth_cache()->UpdateAllFrom(
568 *http_network_session_->http_auth_cache()); 575 *http_network_session_->http_auth_cache());
569 } 576 }
570 577
571 } // namespace gcm 578 } // namespace gcm
OLDNEW
« no previous file with comments | « no previous file | google_apis/gcm/engine/connection_factory_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698