firebase / firebase-ios-sdk

Firebase SDK for Apple App Development
https://firebase.google.com
Apache License 2.0
5.56k stars 1.45k forks source link

Crash: NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: Enqueue methods cannot be called when we are already running on target executor #6909

Closed mpalczew closed 3 years ago

mpalczew commented 3 years ago

[REQUIRED] Step 1: Describe your environment

[REQUIRED] Step 2: Describe the problem

Steps to reproduce:

Observing a crash when trying to delete a FirebaseApp object.

calling

app.delete {
}

where app is a FirebaseApp

Seeing this

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FIRESTORE INTERNAL ASSERTION FAILED: Enqueue methods cannot be called when we are already running on target executor (this queue's executor: 'com.google.firebase.firestore.httpsinstacartfirebaseiocomv1', current executor: 'com.google.firebase.firestore.httpsinstacartfirebaseiocomv1') (expected !is_operation_in_progress_ || !executor_->IsCurrentExecutor())'
var-const commented 3 years ago

Thank you for filing the issue. From the error message, it sounds like you're using Firestore and somehow a callback run on the user callback queue ends up enqueuing another operation that is supposed to be run on the user callback queue. Are you running any code that involves Firestore in the app.delete callback? If that's the case, can you please check whether temporarily commenting that code out prevents the assertion? Another thing that might be helpful would be to enable logging and post the resulting log after reproducing the issue (please make sure to omit any sensitive data).

mpalczew commented 3 years ago

Here are the logs

    10:00:08.556    Instacart Beta  6.34.0 - [Firebase/Core][I-COR000006] Deleting app named httpsinstacartfirebaseiocomv1
    10:00:08.557    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] RemoteStore 7f7f695bed50 shutting down
    10:00:08.557    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] WatchStream (600000217d18) stop
    10:00:08.557    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] WatchStream (600000217d18) Finishing gRPC stream
    10:00:08.557    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] GrpcStream('600000cab3c0'): finishing without notifying observers
    10:00:08.557    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] GrpcStream('600000cab3c0'): shutting down; completions: 1, is finished: false
    10:00:08.558    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] GrpcStream('600000cab3c0'): finishing the underlying call
2   10:00:08.558    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] GrpcStream('600000cab3c0'): fast finishing 1 completion(s)
    10:00:08.558    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] GrpcStream('600000cab3c0'): destroying stream
    10:00:08.559    Instacart Beta  6.34.0 - [Firebase/Firestore][I-FST000001] WriteStream (7f7f5949be48) stop
mpalczew commented 3 years ago

I'm not running any code that involves firestore in the app.delete callback. Waiting for one second before calling delete does seem to work just fine. Trying to figure out if there are any firebase calls around this area. Though I don't see anything and nothing in the logs.

mpalczew commented 3 years ago

Also, Started seeing this after we upgraded from 6.14.0 to 6.33.0. We were not seeing this crash before.

mpalczew commented 3 years ago

This crash seems to happen only if I have active snapshot listeners for a document reference. If I register all snapshot listeners and call remove on them before I delete the app, then this crash doesn't happen.

var-const commented 3 years ago

@mpalczew Thank you for providing additional information. There should be a stack trace associated with the exception, can you please post it?

mpalczew commented 3 years ago
frame #0: 0x00007fff20177f48 libobjc.A.dylib`objc_exception_throw
    frame #1: 0x00007fff20439f4f CoreFoundation`+[NSException raise:format:arguments:] + 88
    frame #2: 0x00007fff20788293 Foundation`-[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 166
    frame #3: 0x000000010e5a4b50 Instacart Beta`firebase::firestore::util::ObjcThrowHandler(firebase::firestore::util::ExceptionType, char const*, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 304
    frame #4: 0x000000010e5a464e Instacart Beta`firebase::firestore::util::Throw(firebase::firestore::util::ExceptionType, char const*, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 10
    frame #5: 0x000000010e5f4436 Instacart Beta`firebase::firestore::util::internal::FailAssertion(char const*, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 22
    frame #6: 0x000000010e5f44fd Instacart Beta`firebase::firestore::util::internal::FailAssertion(char const*, char const*, int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, char const*) + 199
    frame #7: 0x000000010e58bf3f Instacart Beta`firebase::firestore::util::AsyncQueue::VerifySequentialOrder() const + 157
    frame #8: 0x000000010e58be74 Instacart Beta`firebase::firestore::util::AsyncQueue::EnterRestrictedMode() + 30
    frame #9: 0x000000010e5c7cf3 Instacart Beta`firebase::firestore::core::FirestoreClient::Dispose() + 39
    frame #10: 0x000000010e5bbd9a Instacart Beta`firebase::firestore::api::Firestore::Dispose() + 42
    frame #11: 0x000000010e5bbc7d Instacart Beta`firebase::firestore::api::Firestore::~Firestore() + 15
    frame #12: 0x000000010e5b7bb1 Instacart Beta`std::__1::shared_ptr<firebase::firestore::api::Firestore>::~shared_ptr() + 49
    frame #13: 0x000000010e59b89e Instacart Beta`firebase::firestore::api::DocumentReference::AddSnapshotListener(firebase::firestore::core::ListenOptions, std::__1::unique_ptr<firebase::firestore::core::EventListener<firebase::firestore::api::DocumentSnapshot>, std::__1::default_delete<firebase::firestore::core::EventListener<firebase::firestore::api::DocumentSnapshot> > >&&)::Converter::~Converter() + 58
    frame #14: 0x000000010e5dd14c Instacart Beta`firebase::firestore::core::AsyncEventListener<firebase::firestore::core::ViewSnapshot>::~AsyncEventListener() + 44
    frame #15: 0x000000010e641d07 Instacart Beta`std::__1::shared_ptr<firebase::firestore::core::EventListener<firebase::firestore::core::ViewSnapshot> >::~shared_ptr() + 49
    frame #16: 0x000000010e641821 Instacart Beta`firebase::firestore::core::QueryListener::~QueryListener() + 223
    frame #17: 0x000000010e5cc3e9 Instacart Beta`std::__1::shared_ptr<firebase::firestore::core::QueryListener>::~shared_ptr() + 49
    frame #18: 0x000000010e5a2d4a Instacart Beta`std::__1::__vector_base<std::__1::shared_ptr<firebase::firestore::core::QueryListener>, std::__1::allocator<std::__1::shared_ptr<firebase::firestore::core::QueryListener> > >::~__vector_base() + 42
    frame #19: 0x000000010e5a2ccf Instacart Beta`void std::__1::allocator_traits<std::__1::allocator<std::__1::__hash_node<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, void*> > >::destroy<std::__1::pair<firebase::firestore::core::Query const, firebase::firestore::core::EventManager::QueryListenersInfo> >(std::__1::allocator<std::__1::__hash_node<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, void*> >&, std::__1::pair<firebase::firestore::core::Query const, firebase::firestore::core::EventManager::QueryListenersInfo>*) + 213
    frame #20: 0x000000010e5a2be5 Instacart Beta`std::__1::__hash_table<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::__unordered_map_hasher<firebase::firestore::core::Query, std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::hash<firebase::firestore::core::Query>, true>, std::__1::__unordered_map_equal<firebase::firestore::core::Query, std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::equal_to<firebase::firestore::core::Query>, true>, std::__1::allocator<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo> > >::__deallocate_node(std::__1::__hash_node_base<std::__1::__hash_node<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, void*>*>*) + 27
    frame #21: 0x000000010e5a2bae Instacart Beta`std::__1::__hash_table<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::__unordered_map_hasher<firebase::firestore::core::Query, std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::hash<firebase::firestore::core::Query>, true>, std::__1::__unordered_map_equal<firebase::firestore::core::Query, std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo>, std::__1::equal_to<firebase::firestore::core::Query>, true>, std::__1::allocator<std::__1::__hash_value_type<firebase::firestore::core::Query, firebase::firestore::core::EventManager::QueryListenersInfo> > >::~__hash_table() + 18
    frame #22: 0x000000010e5a2b1d Instacart Beta`firebase::firestore::core::EventManager::~EventManager() + 37
    frame #23: 0x000000010e5c804c Instacart Beta`firebase::firestore::core::FirestoreClient::TerminateInternal() + 264
    frame #24: 0x000000010e5cada0 Instacart Beta`std::__1::__function::__func<firebase::firestore::core::FirestoreClient::TerminateAsync(std::__1::function<void (firebase::firestore::util::Status)>)::$_5, std::__1::allocator<firebase::firestore::core::FirestoreClient::TerminateAsync(std::__1::function<void (firebase::firestore::util::Status)>)::$_5>, void ()>::operator()() + 46
    frame #25: 0x000000010e58c161 Instacart Beta`firebase::firestore::util::AsyncQueue::ExecuteBlocking(std::__1::function<void ()> const&) + 49
    frame #26: 0x000000010e676e3f Instacart Beta`firebase::firestore::util::Task::ExecuteAndRelease() + 181
    frame #27: 0x000000011f7dca88 libdispatch.dylib`_dispatch_client_callout + 8
    frame #28: 0x000000011f7e3356 libdispatch.dylib`_dispatch_lane_serial_drain + 796
    frame #29: 0x000000011f7e4027 libdispatch.dylib`_dispatch_lane_invoke + 439
    frame #30: 0x000000011f7efe90 libdispatch.dylib`_dispatch_workloop_worker_thread + 882
    frame #31: 0x00007fff5dfa5a3d libsystem_pthread.dylib`_pthread_wqthread + 290
    frame #32: 0x00007fff5dfa4b77 libsystem_pthread.dylib`start_wqthread + 15
var-const commented 3 years ago

Thank you for providing the stack trace! This is a bug that happens when during termination the only remaining reference to the Firestore instance is in a listener.

The crash should be prevented if you don't dispose your reference to Firestore until the call to delete is finished. Can you please try that and see if that works for you?

mpalczew commented 3 years ago

Looks like holding on to the firestore until delete is finished worked too.

Our current workaround is to remove all our listeners.

var-const commented 3 years ago

Glad to hear it works, please use the approach that is the most convenient.

I filed an internal bug: b/172958106. I will close this issue for now because there is a workaround in place and there's no immediate action to be taken; I'll update the issue when the fix is ready.