firebase-ios-sdk icon indicating copy to clipboard operation
firebase-ios-sdk copied to clipboard

Data Race on gIsNewDatabase in RCNConfigDBManager (FirebaseRemoteConfig)

Open dooublemint opened this issue 8 months ago • 3 comments

Description

Hello Firebase team,

I'm encountering a data race warning when using FirebaseRemoteConfig. The issue is related to a global variable gIsNewDatabase being accessed from multiple threads without synchronization.

Details: SDK: firebase-ios-sdk Module: FirebaseRemoteConfig File: RCNConfigDBManager.m Line: 1222 (and method - (BOOL)isNewDatabase) Detected using: Thread Sanitizer (Xcode)

Reproducing the issue

No response

Firebase SDK Version

11.11.0

Xcode Version

16.1

Installation Method

Swift Package Manager

Firebase Product(s)

Analytics, Remote Config, Crashlytics, AB Testing

Targeted Platforms

iOS

Relevant Log Output

'gIsNewDatabase' is a global variable (0x1049a7f48)
/Users/admin/Library/Developer/Xcode/DerivedData/myProject-.../FirebaseRemoteConfig/Sources/RCNConfigDBManager.m:1222
Data race in -[RCNConfigDBManager isNewDatabase] at gIsNewDatabase

If using Swift Package Manager, the project's Package.resolved

Expand Package.resolved snippet

Replace this line with the contents of your Package.resolved.

If using CocoaPods, the project's Podfile.lock

Expand Podfile.lock snippet

Replace this line with the contents of your Podfile.lock!

dooublemint avatar Apr 15 '25 09:04 dooublemint

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

google-oss-bot avatar Apr 15 '25 09:04 google-oss-bot

Thanks for the report, @dooublemint. Could you provide the reproducing steps on how you encounter the issue?

rizafran avatar Apr 15 '25 13:04 rizafran

I've confirmed this is a real issue, at least theoretically, while doing the Swift migration. I'll leave open. Please thumbs up if it impacts you and ideally provide a repro case.

paulb777 avatar Jun 06 '25 14:06 paulb777

Some Trace that might help:

==================
WARNING: ThreadSanitizer: data race (pid=30889)
  Write of size 1 at 0x00010790a338 by thread T3:
    #0 RemoteConfigCreateFilePathIfNotExist <null> (App:arm64+0x102175a1c)
    #1 __42-[RCNConfigDBManager createOrOpenDatabase]_block_invoke <null> (App:arm64+0x1021754e4)
    #2 __tsan::invoke_and_release_block(void*) <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x7f8d0)
    #3 _dispatch_client_callout <null> (libdispatch.dylib:arm64+0x1d794)

  Previous read of size 1 at 0x00010790a338 by main thread (mutexes: write M0, write M1):
    #0 -[RCNConfigDBManager isNewDatabase] <null> (App:arm64+0x102181c44)
    #1 -[RCNConfigSettings initWithDatabaseManager:namespace:firebaseAppName:googleAppID:] <null> (App:arm64+0x102194f30)
    #2 -[FIRRemoteConfig initWithAppName:FIROptions:namespace:DBManager:configContent:analytics:] <null> (App:arm64+0x102161acc)
    #3 -[FIRRemoteConfigComponent remoteConfigForNamespace:] <null> (App:arm64+0x10216d680)
    #4 -[FIRRemoteConfigComponent registerRolloutsStateSubscriber:for:] <null> (App:arm64+0x10216dfec)
    #5 -[FIRCrashlytics initWithApp:appInfo:installations:analytics:sessions:remoteConfig:] <null> (App:arm64+0x1018b5ea4)
    #6 __38+[FIRCrashlytics componentsToRegister]_block_invoke <null> (App:arm64+0x1018b69f0)
    #7 -[FIRComponentContainer instantiateInstanceForProtocol:withBlock:] <null> (App:arm64+0x101943878)
    #8 -[FIRComponentContainer instanceForProtocol:] <null> (App:arm64+0x101943d7c)
    #9 -[FIRComponentContainer instantiateEagerComponents] <null> (App:arm64+0x101943624)
    #10 +[FIRApp configureWithName:options:] <null> (App:arm64+0x10193b77c)
    #11 +[FIRApp configureWithOptions:] <null> (App:arm64+0x10193adc4)
    #12 (1) suspend resume partial function for App.FirebaseRepository.(initialize in _3E95AD6ADDB109205B372892D4B17379)() async -> () <null> (App:arm64+0x1012f722c)
    #13 swift::runJobInEstablishedExecutorContext(swift::Job*) <null> (libswift_Concurrency.dylib:arm64+0x3e984)
    #14 static App.AppDelegate.$main() -> () <null> (App:arm64+0x1001ed9b4)
    #15 main <null> (App:arm64+0x1001f0550)

  Location is global 'gIsNewDatabase' at 0x00010790a338 (App+0x10376a338)

  Mutex M0 (0x00010781b848) created at:
    #0 objc_sync_enter <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x7d2d8)
    #1 +[FIRApp configureWithName:options:] <null> (App:arm64+0x10193b638)
    #2 +[FIRApp configureWithOptions:] <null> (App:arm64+0x10193adc4)
    #3 (1) suspend resume partial function for App.FirebaseRepository.(initialize in _3E95AD6ADDB109205B372892D4B17379)() async -> () <null> (App:arm64+0x1012f722c)
    #4 swift::runJobInEstablishedExecutorContext(swift::Job*) <null> (libswift_Concurrency.dylib:arm64+0x3e984)
    #5 static App.AppDelegate.$main() -> () <null> (App:arm64+0x1001ed9b4)
    #6 main <null> (App:arm64+0x1001f0550)

  Mutex M1 (0x00011f966a50) created at:
    #0 objc_sync_enter <null> (libclang_rt.tsan_iossim_dynamic.dylib:arm64+0x7d2d8)
    #1 -[FIRComponentContainer instanceForProtocol:] <null> (App:arm64+0x101943c1c)
    #2 +[FIRComponentType instanceForProtocol:inContainer:] <null> (App:arm64+0x101944cf0)
    #3 +[FIRInstallations installationsWithApp:] <null> (App:arm64+0x10196c628)
    #4 +[FIRInstallations installations] <null> (App:arm64+0x10196c4fc)
    #5 +[FIRAnalytics updateFirebaseInstallationID] <null> (App:arm64+0x1029390cc)
    #6 +[FIRApp addAppToAppDictionary:] <null> (App:arm64+0x10193c904)
    #7 +[FIRApp configureWithName:options:] <null> (App:arm64+0x10193b740)
    #8 +[FIRApp configureWithOptions:] <null> (App:arm64+0x10193adc4)
    #9 (1) suspend resume partial function for App.FirebaseRepository.(initialize in _3E95AD6ADDB109205B372892D4B17379)() async -> () <null> (App:arm64+0x1012f722c)
    #10 swift::runJobInEstablishedExecutorContext(swift::Job*) <null> (libswift_Concurrency.dylib:arm64+0x3e984)
    #11 static App.AppDelegate.$main() -> () <null> (App:arm64+0x1001ed9b4)
    #12 main <null> (App:arm64+0x1001f0550)

  Thread T3 (tid=5032809, running) is a GCD worker thread

lifely avatar Sep 24 '25 10:09 lifely

Hi all, apologies for the confusion, this bug was fixed in Firebase 12.6.0 via #15442. Please update to 12.6.0 or newer to get the fix. Thanks for the report!

ncooke3 avatar Dec 02 '25 21:12 ncooke3