Skip to content

Commit 80940c0

Browse files
authored
Firestore: Fix data race in credentials provider (#10403)
1 parent e9ba9eb commit 80940c0

File tree

3 files changed

+26
-1
lines changed

3 files changed

+26
-1
lines changed

Firestore/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Unreleased
22
- [fixed] Fix FAILED_PRECONDITION when writing to a deleted document in a
33
transaction (#10431).
4+
- [fixed] Fixed data race in credentials provider (#10393).
45

56
# 10.0.0
67
- [feature] Added `Query.count()`, which fetches the number of documents in the

Firestore/core/src/credentials/credentials_provider.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#ifndef FIRESTORE_CORE_SRC_CREDENTIALS_CREDENTIALS_PROVIDER_H_
1818
#define FIRESTORE_CORE_SRC_CREDENTIALS_CREDENTIALS_PROVIDER_H_
1919

20+
#include <atomic>
2021
#include <functional>
2122
#include <string>
2223

@@ -46,6 +47,7 @@ template <class TokenType, class ValueType>
4647
class CredentialsProvider {
4748
public:
4849
CredentialsProvider() : change_listener_(nullptr) {
50+
force_refresh_ = false;
4951
}
5052

5153
virtual ~CredentialsProvider() = default;
@@ -81,7 +83,7 @@ class CredentialsProvider {
8183
*/
8284
CredentialChangeListener<ValueType> change_listener_;
8385

84-
bool force_refresh_ = false;
86+
std::atomic<bool> force_refresh_;
8587
};
8688

8789
} // namespace credentials

Firestore/core/test/unit/credentials/firebase_auth_credentials_provider_test.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,28 @@ - (void)getTokenForcingRefresh:(BOOL)forceRefresh
153153
});
154154
}
155155

156+
// Catch race conditions in FirebaseAuthCredentialsProvider::GetToken() when
157+
// run under thread sanitizer.
158+
// See https://github.com/firebase/firebase-ios-sdk/issues/10393
159+
TEST(FirebaseAuthCredentialsProviderTest, GetTokenCalledByAnotherThread) {
160+
FIRApp* app = testutil::AppForUnitTesting();
161+
FSTAuthFake* auth = [[FSTAuthFake alloc] initWithToken:@"token for fake uid"
162+
uid:@"fake uid"];
163+
FirebaseAuthCredentialsProvider credentials_provider(app, auth);
164+
165+
std::thread thread1([&credentials_provider] {
166+
credentials_provider.GetToken(
167+
[](util::StatusOr<AuthToken> result) { EXPECT_TRUE(result.ok()); });
168+
});
169+
std::thread thread2([&credentials_provider] {
170+
credentials_provider.GetToken(
171+
[](util::StatusOr<AuthToken> result) { EXPECT_TRUE(result.ok()); });
172+
});
173+
174+
thread1.join();
175+
thread2.join();
176+
}
177+
156178
} // namespace credentials
157179
} // namespace firestore
158180
} // namespace firebase

0 commit comments

Comments
 (0)