Description
[REQUIRED] Please fill in the following fields:
- Pre-built SDK from the website or open-source from this repo: website
- Firebase C++ SDK version: 7.1.1
- Main Firebase Components in concern: Firestore, Storage
- Other Firebase Components in use: Auth
- Platform you are using the C++ SDK on: Mac
- Platform you are targeting: iOS
[REQUIRED] Please describe the question here:
Briefly
Is it safe to call other firebase methods from a future OnCompletion
handler? That is, start a second (or more) asynchronous task when the first completes?
In detail
This is potentially a regression, but could be a misuse of the API on our part. We've been using Firebase 6.15.1 successfully for a while and decided it was past time to upgrade to 7.1.1. We have a design where configuration is stored in Firestore, which tells the app which files are required from Cloud Storage. So for one call to our internal function we need a call to Firestore followed by a call to Storage. Simplified code would be something like:
void getCorrectFile( const char* localPath, std::function<void(const std::string& errorMessage)> callback )
{
pFirestore->Collection("configStuff").Get().OnCompletion(
[callback=std::move(callback)]( const ::firebase::Future<firebase::firestore::QuerySnapshot>& collectionFuture )
{
if( collectionFuture.error() != firebase::firestore::Error::kErrorOk )
{
callback( "An error occurred (real code maps errors to error_codes)" );
}
else
{
// ...code to work out correct file from the QuerySnapshot...
firebase::storage::StorageReference fileRef = pStorage->GetReference(firebasePath);
fileRef.GetFile(localPath).OnCompletion( [callback=std::move(callback),fileRef](const firebase::Future<size_t>& getFileFuture)
{
if( getFileFuture.error() != 0 ) callback( getFileFuture.error_message() );
else callback( "No error (real code would create default constructed error_code)" );
} );
}
} );
}
As I say, this all worked fine in Firebase 6.15.1. After upgrading to 7.1.1 we now get various crashes[*]. Before investigating I thought it was worth checking we're not fundamentally abusing the thread model in the API, and it just happened to work previously.
[*] How it crashes is fairly inconsistent. It can be an assert from some mutex.h file, or an unhandled *** -[NSFileManager createDirectoryAtURL:withIntermediateDirectories:attributes:error:]: URL is nil
exception. I've even seen it work once.