Commit 59a502e3 authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Fix crash in GCM if multiple errors reported

In subtle cases like state CONNECTING being entered via
MCSClient::ResetStateAndBuildLoginRequest(), it is possible that the
error callback gets triggered twice.

With OnceCallback() being adopted recently in
https://chromium-review.googlesource.com/c/chromium/src/+/1939891, this
leads to a crash, and surfaced by flakiness in sync integration tests.

Bug: 1039598
Change-Id: Iad23dfe81e07f11939a6640fb792a7ae1386c397
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1991434
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Auto-Submit: Mikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarDmitry Titov <dimich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#729799}
parent 8195304e
...@@ -187,14 +187,14 @@ MCSClient::~MCSClient() { ...@@ -187,14 +187,14 @@ MCSClient::~MCSClient() {
} }
void MCSClient::Initialize( void MCSClient::Initialize(
ErrorCallback error_callback, const ErrorCallback& error_callback,
const OnMessageReceivedCallback& message_received_callback, const OnMessageReceivedCallback& message_received_callback,
const OnMessageSentCallback& message_sent_callback, const OnMessageSentCallback& message_sent_callback,
std::unique_ptr<GCMStore::LoadResult> load_result) { std::unique_ptr<GCMStore::LoadResult> load_result) {
DCHECK_EQ(state_, UNINITIALIZED); DCHECK_EQ(state_, UNINITIALIZED);
state_ = LOADED; state_ = LOADED;
mcs_error_callback_ = std::move(error_callback); mcs_error_callback_ = error_callback;
message_received_callback_ = message_received_callback; message_received_callback_ = message_received_callback;
message_sent_callback_ = message_sent_callback; message_sent_callback_ = message_sent_callback;
...@@ -238,7 +238,7 @@ void MCSClient::Initialize( ...@@ -238,7 +238,7 @@ void MCSClient::Initialize(
if (!base::StringToUint64(iter->first, &timestamp)) { if (!base::StringToUint64(iter->first, &timestamp)) {
LOG(ERROR) << "Invalid restored message."; LOG(ERROR) << "Invalid restored message.";
// TODO(fgorski): Error: data unreadable // TODO(fgorski): Error: data unreadable
std::move(mcs_error_callback_).Run(); mcs_error_callback_.Run();
return; return;
} }
...@@ -708,7 +708,7 @@ void MCSClient::HandlePacketFromWire( ...@@ -708,7 +708,7 @@ void MCSClient::HandlePacketFromWire(
LOG(ERROR) << "Failed to log in to GCM, resetting connection."; LOG(ERROR) << "Failed to log in to GCM, resetting connection.";
connection_factory_->SignalConnectionReset( connection_factory_->SignalConnectionReset(
ConnectionFactory::LOGIN_FAILURE); ConnectionFactory::LOGIN_FAILURE);
std::move(mcs_error_callback_).Run(); mcs_error_callback_.Run();
return; return;
} }
......
...@@ -84,10 +84,12 @@ class GCM_EXPORT MCSClient { ...@@ -84,10 +84,12 @@ class GCM_EXPORT MCSClient {
SEND_STATUS_COUNT SEND_STATUS_COUNT
}; };
// Callback for MCSClient's error conditions. // Callback for MCSClient's error conditions. A repeating callback is used
// because occasionally multiple errors are reported, see crbug.com/1039598
// for more context.
// TODO(fgorski): Keeping it as a callback with intention to add meaningful // TODO(fgorski): Keeping it as a callback with intention to add meaningful
// error information. // error information.
using ErrorCallback = base::OnceCallback<void()>; using ErrorCallback = base::RepeatingClosure;
// Callback when a message is received. // Callback when a message is received.
using OnMessageReceivedCallback = using OnMessageReceivedCallback =
base::RepeatingCallback<void(const MCSMessage& message)>; base::RepeatingCallback<void(const MCSMessage& message)>;
...@@ -116,7 +118,7 @@ class GCM_EXPORT MCSClient { ...@@ -116,7 +118,7 @@ class GCM_EXPORT MCSClient {
// |success == true|. // |success == true|.
// If an error loading the GCM store is encountered, // If an error loading the GCM store is encountered,
// |initialization_callback| will be invoked with |success == false|. // |initialization_callback| will be invoked with |success == false|.
void Initialize(ErrorCallback initialization_callback, void Initialize(const ErrorCallback& initialization_callback,
const OnMessageReceivedCallback& message_received_callback, const OnMessageReceivedCallback& message_received_callback,
const OnMessageSentCallback& message_sent_callback, const OnMessageSentCallback& message_sent_callback,
std::unique_ptr<GCMStore::LoadResult> load_result); std::unique_ptr<GCMStore::LoadResult> load_result);
......
...@@ -319,7 +319,7 @@ void MCSProbe::LoadCallback(std::unique_ptr<GCMStore::LoadResult> load_result) { ...@@ -319,7 +319,7 @@ void MCSProbe::LoadCallback(std::unique_ptr<GCMStore::LoadResult> load_result) {
DVLOG(1) << "Loaded MCS id " << android_id_; DVLOG(1) << "Loaded MCS id " << android_id_;
} }
mcs_client_->Initialize( mcs_client_->Initialize(
base::BindOnce(&MCSProbe::ErrorCallback, base::Unretained(this)), base::BindRepeating(&MCSProbe::ErrorCallback, base::Unretained(this)),
base::BindRepeating(&MessageReceivedCallback), base::BindRepeating(&MessageReceivedCallback),
base::BindRepeating(&MessageSentCallback), std::move(load_result)); base::BindRepeating(&MessageSentCallback), std::move(load_result));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment