firebase / firebase-android-sdk

Firebase Android SDK
https://firebase.google.com
Apache License 2.0
2.26k stars 573 forks source link

Firestore Crash: SQLiteDatabaseLockedException #953

Closed MTermLyo closed 3 years ago

MTermLyo commented 4 years ago

[REQUIRED] Step 2: Describe your environment

[REQUIRED] Step 3: Describe the problem

The results that we got from Firebase Crashlytics show that some users faced the problem with Firestore. One of the errors described below says that: This generally means you are using Cloud Firestore from multiple processes in your app -> We are accessing it always in the same process.

isPersistenceEnabled = true // by default

**Fatal Exception: java.lang.RuntimeException
Internal error in Cloud Firestore (21.1.1).**
com.google.firebase.firestore.util.AsyncQueue.lambda$panic$3 (AsyncQueue.java:529)
com.google.firebase.firestore.util.AsyncQueue$$Lambda$3.run (AsyncQueue.java:2)
android.os.Handler.handleCallback (Handler.java:873)
android.os.Handler.dispatchMessage (Handler.java:99)
android.os.Looper.loop (Looper.java:193)
android.app.ActivityThread.main (ActivityThread.java:6746)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:499)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)

**Caused by java.lang.RuntimeException
java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them.**
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1 (AsyncQueue.java:320)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run (AsyncQueue.java:4)
java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:458)
java.util.concurrent.FutureTask.run (FutureTask.java:266)
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:301)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run (AsyncQueue.java:224)
java.lang.Thread.run (Thread.java:764)

**Caused by java.lang.RuntimeException
Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them.**
com.google.firebase.firestore.local.SQLitePersistence.start (SQLitePersistence.java:157)
com.google.firebase.firestore.core.FirestoreClient.initialize (FirestoreClient.java:270)
com.google.firebase.firestore.core.FirestoreClient.lambda$new$2 (FirestoreClient.java:118)
com.google.firebase.firestore.core.FirestoreClient$$Lambda$2.run (FirestoreClient.java:8)
com.google.firebase.firestore.util.AsyncQueue.lambda$enqueue$2 (AsyncQueue.java:431)
com.google.firebase.firestore.util.AsyncQueue$$Lambda$2.call (AsyncQueue.java:2)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1 (AsyncQueue.java:317)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run (AsyncQueue.java:4)
java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:458)
java.util.concurrent.FutureTask.run (FutureTask.java:266)
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:301)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run (AsyncQueue.java:224)
java.lang.Thread.run (Thread.java:764)

**Caused by android.database.sqlite.SQLiteDatabaseLockedException
database is locked (code 5 SQLITE_BUSY)**
android.database.sqlite.SQLiteConnection.nativeExecute (SQLiteConnection.java)
android.database.sqlite.SQLiteConnection.execute (SQLiteConnection.java:569)
android.database.sqlite.SQLiteSession.beginTransactionUnchecked (SQLiteSession.java:323)
android.database.sqlite.SQLiteSession.beginTransaction (SQLiteSession.java:298)
android.database.sqlite.SQLiteDatabase.beginTransaction (SQLiteDatabase.java:549)
android.database.sqlite.SQLiteDatabase.beginTransaction (SQLiteDatabase.java:460)
android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked (SQLiteOpenHelper.java:390)
android.database.sqlite.SQLiteOpenHelper.getWritableDatabase (SQLiteOpenHelper.java:298)
com.google.firebase.firestore.local.SQLitePersistence.start (SQLitePersistence.java:154)
com.google.firebase.firestore.core.FirestoreClient.initialize (FirestoreClient.java:270)
com.google.firebase.firestore.core.FirestoreClient.lambda$new$2 (FirestoreClient.java:118)
com.google.firebase.firestore.core.FirestoreClient$$Lambda$2.run (FirestoreClient.java:8)
com.google.firebase.firestore.util.AsyncQueue.lambda$enqueue$2 (AsyncQueue.java:431)
com.google.firebase.firestore.util.AsyncQueue$$Lambda$2.call (AsyncQueue.java:2)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1 (AsyncQueue.java:317)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run (AsyncQueue.java:4)
java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:458)
java.util.concurrent.FutureTask.run (FutureTask.java:266)
java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:301)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run (AsyncQueue.java:224)
java.lang.Thread.run (Thread.java:764)
wilhuff commented 4 years ago

Are you by chance calling Firestore from multiple threads very early in the life of your application?

MTermLyo commented 4 years ago

Are you by chance calling Firestore from multiple threads very early in the life of your application?

No, we are calling Firestore always from "Thread[main,5,main]". From the logs that we got, we tried to reproduce the error in real devices like: Xiaomi Mi A1, Huawei Mate 9 but without success.

wilhuff commented 4 years ago

Hrm. We recently found an initialization race condition in the iOS port (firebase/firebase-ios-sdk#3967), but I could not find an equivalent issue with on Android. If you were using multiple threads that could have pointed to a similar issue here.

Since you're not using multiple threads I don't have much to offer you: the exception indicates that one instance of Firestore has the underlying database open and then somehow you're managing to start another one. I'll consult internally to see if there are any other explanations for this, but without a way to reproduce and understand how this is happening we're not going to be able to make much progress on this.

wilhuff commented 4 years ago

Could you post your fully merged manifest? Note that if all the crashes are coming from the main thread that might might something else is opening Firestore first.

MTermLyo commented 4 years ago

Could you post your fully merged manifest? Note that if all the crashes are coming from the main thread that might might something else is opening Firestore first.

Apologies for the delay. Although the crashes are coming from the main thread, we are opening the Firestore in the main thread. We are handling always the same instance of the Firestore.

I would like to mention something interesting. Almost all the crashes are coming from the same device type: Xiaomi Blackshark 1 (Android 9). When I searched in Google I found also that other app had a similar issue with the Firestore-SQLiteDatabaseLockedException from the mentioned device type.

I realized that Xiaomi Blackshark 1 is a niche device (gaming phone), so I'm not sure if this problem could be something between this device type and Firebase SDK. We do not own this type of device so I'm not able to reproduce the error in other devices/emulators.

pupaconnect commented 4 years ago

Yes. Only BlackShark Has the issue. We do not know how to fix it.

wilhuff commented 4 years ago

I've checked and unfortunately we don't have any of these devices with which to test either.

How prevalent is this issue?

If possible could you collect logs from affected devices? You can enable logging like so: https://gist.github.com/katowulf/0475fb7a5907ed757f687aab6ed15878.

Unfortunately, this only reports log messages logcat, which does not get collected by Crashlytics. You could capture logcat messages using something like this: https://github.com/Ereza/LogcatReporter.

Absent more data on how this is happening or a way to reproduce this issue there isn't much we can do about it.

sapjunior commented 4 years ago

I also encounter this problem as well on user device Xiaomi Shark (but with firebase realtime database). The program will crash when offline persistence is enabled. Here is the error from crashlytics

java.lang.RuntimeException: 
  at com.google.firebase.database.android.AndroidPlatform$1$1.run (AndroidPlatform.java)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:193)
  at android.app.ActivityThread.main (ActivityThread.java:6758)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:499)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:858)
Caused by: com.google.firebase.database.DatabaseException: 
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.buildAncestorWhereClause (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.commaSeparatedList (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.deserializeNode (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.joinBytes (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.loadTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.loadUserWrites (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.mergeIntoServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.mergeIntoServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.openDatabase (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.partKey (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pathPrefixStartToPrefixEnd (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pruneCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pruneTreeRecursive (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.removeNested (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.removeUserWrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveTrackedQuery (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveUserMerge (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveUserOverwrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveWrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.serializeObject (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.serverCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.splitBytes (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.splitNodeRunLength (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.updateServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.updateTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.<init> (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.AndroidPlatform.access$000 (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.createPersistenceManager (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.getSSLCacheDirectory (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.getUserAgent (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.newLogger (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.newPersistentConnection (AndroidPlatform.java)
  at com.google.firebase.database.core.Context.freeze (Context.java)
  at com.google.firebase.database.core.Context.getPersistenceManager (Context.java)
  at com.google.firebase.database.core.Repo.access$200 (Repo.java)
  at com.google.firebase.database.core.Repo.deferredInitialization (Repo.java)
  at com.google.firebase.database.core.Repo.abortTransactions (Repo.java)
  at com.google.firebase.database.core.Repo.abortTransactionsAtNode (Repo.java)
  at com.google.firebase.database.core.Repo.access$000 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1100 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1200 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1900 (Repo.java)
  at com.google.firebase.database.core.Repo.access$3000 (Repo.java)
  at com.google.firebase.database.core.Repo.access$3100 (Repo.java)
  at com.google.firebase.database.core.Repo.access$500 (Repo.java)
  at com.google.firebase.database.core.Repo.access$600 (Repo.java)
  at com.google.firebase.database.core.Repo.access$700 (Repo.java)
  at com.google.firebase.database.core.Repo.access$800 (Repo.java)
  at com.google.firebase.database.core.Repo.ackWriteAndRerunTransactions (Repo.java)
  at com.google.firebase.database.core.Repo.addEventCallback (Repo.java)
  at com.google.firebase.database.core.Repo.aggregateTransactionQueues (Repo.java)
  at com.google.firebase.database.core.Repo.buildTransactionQueue (Repo.java)
  at com.google.firebase.database.core.Repo.callOnComplete (Repo.java)
  at com.google.firebase.database.core.Repo.getAncestorTransactionNode (Repo.java)
  at com.google.firebase.database.core.Repo.getLatestState (Repo.java)
  at com.google.firebase.database.core.Repo.keepSynced (Repo.java)
  at com.google.firebase.database.core.Repo.onAuthStatus (Repo.java)
  at com.google.firebase.database.core.Repo.onConnect (Repo.java)
  at com.google.firebase.database.core.Repo.onDataUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectCancel (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectSetValue (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onRangeMergeUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onServerInfoUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onServerInfoUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.postEvent (Repo.java)
  at com.google.firebase.database.core.Repo.postEvents (Repo.java)
  at com.google.firebase.database.core.Repo.rerunTransactionQueue (Repo.java)
  at com.google.firebase.database.core.Repo.restoreWrites (Repo.java)
  at com.google.firebase.database.core.Repo.startTransaction (Repo.java)
  at com.google.firebase.database.core.Repo.updateChildren (Repo.java)
  at com.google.firebase.database.core.Repo.warnIfWriteFailed (Repo.java)
  at com.google.firebase.database.core.Repo$1.run (Repo.java)
  at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:458)
  at java.util.concurrent.FutureTask.run (FutureTask.java:266)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:301)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
  at java.lang.Thread.run (Thread.java:764)
Caused by: android.database.sqlite.SQLiteDatabaseLockedException: 
  at android.database.sqlite.SQLiteConnection.nativeExecute (SQLiteConnection.java)
  at android.database.sqlite.SQLiteConnection.execute (SQLiteConnection.java:572)
  at android.database.sqlite.SQLiteSession.beginTransactionUnchecked (SQLiteSession.java:323)
  at android.database.sqlite.SQLiteSession.beginTransaction (SQLiteSession.java:298)
  at android.database.sqlite.SQLiteDatabase.beginTransaction (SQLiteDatabase.java:549)
  at android.database.sqlite.SQLiteDatabase.beginTransaction (SQLiteDatabase.java:460)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.buildAncestorWhereClause (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.commaSeparatedList (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.deserializeNode (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.joinBytes (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.loadTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.loadUserWrites (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.mergeIntoServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.mergeIntoServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.openDatabase (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.partKey (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pathPrefixStartToPrefixEnd (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pruneCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.pruneTreeRecursive (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.removeNested (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.removeUserWrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveTrackedQuery (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveUserMerge (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveUserOverwrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.saveWrite (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.serializeObject (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.serverCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.splitBytes (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.splitNodeRunLength (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.updateServerCache (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.updateTrackedQueryKeys (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.SqlPersistenceStorageEngine.<init> (SqlPersistenceStorageEngine.java)
  at com.google.firebase.database.android.AndroidPlatform.access$000 (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.createPersistenceManager (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.getSSLCacheDirectory (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.getUserAgent (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.newLogger (AndroidPlatform.java)
  at com.google.firebase.database.android.AndroidPlatform.newPersistentConnection (AndroidPlatform.java)
  at com.google.firebase.database.core.Context.freeze (Context.java)
  at com.google.firebase.database.core.Context.getPersistenceManager (Context.java)
  at com.google.firebase.database.core.Repo.access$200 (Repo.java)
  at com.google.firebase.database.core.Repo.deferredInitialization (Repo.java)
  at com.google.firebase.database.core.Repo.abortTransactions (Repo.java)
  at com.google.firebase.database.core.Repo.abortTransactionsAtNode (Repo.java)
  at com.google.firebase.database.core.Repo.access$000 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1100 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1200 (Repo.java)
  at com.google.firebase.database.core.Repo.access$1900 (Repo.java)
  at com.google.firebase.database.core.Repo.access$3000 (Repo.java)
  at com.google.firebase.database.core.Repo.access$3100 (Repo.java)
  at com.google.firebase.database.core.Repo.access$500 (Repo.java)
  at com.google.firebase.database.core.Repo.access$600 (Repo.java)
  at com.google.firebase.database.core.Repo.access$700 (Repo.java)
  at com.google.firebase.database.core.Repo.access$800 (Repo.java)
  at com.google.firebase.database.core.Repo.ackWriteAndRerunTransactions (Repo.java)
  at com.google.firebase.database.core.Repo.addEventCallback (Repo.java)
  at com.google.firebase.database.core.Repo.aggregateTransactionQueues (Repo.java)
  at com.google.firebase.database.core.Repo.buildTransactionQueue (Repo.java)
  at com.google.firebase.database.core.Repo.callOnComplete (Repo.java)
  at com.google.firebase.database.core.Repo.getAncestorTransactionNode (Repo.java)
  at com.google.firebase.database.core.Repo.getLatestState (Repo.java)
  at com.google.firebase.database.core.Repo.keepSynced (Repo.java)
  at com.google.firebase.database.core.Repo.onAuthStatus (Repo.java)
  at com.google.firebase.database.core.Repo.onConnect (Repo.java)
  at com.google.firebase.database.core.Repo.onDataUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectCancel (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectSetValue (Repo.java)
  at com.google.firebase.database.core.Repo.onDisconnectUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onRangeMergeUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onServerInfoUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.onServerInfoUpdate (Repo.java)
  at com.google.firebase.database.core.Repo.postEvent (Repo.java)
  at com.google.firebase.database.core.Repo.postEvents (Repo.java)
  at com.google.firebase.database.core.Repo.rerunTransactionQueue (Repo.java)
  at com.google.firebase.database.core.Repo.restoreWrites (Repo.java)
  at com.google.firebase.database.core.Repo.startTransaction (Repo.java)
  at com.google.firebase.database.core.Repo.updateChildren (Repo.java)
  at com.google.firebase.database.core.Repo.warnIfWriteFailed (Repo.java)
  at com.google.firebase.database.core.Repo$1.run (Repo.java)
  at java.util.concurrent.Executors$RunnableAdapter.call (Executors.java:458)
  at java.util.concurrent.FutureTask.run (FutureTask.java:266)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run (ScheduledThreadPoolExecutor.java:301)
  at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
  at java.lang.Thread.run (Thread.java:764)
mikelehen commented 4 years ago

@sapjunior Very interesting! Thanks for letting us know. That strongly suggests this is not specific to our code (since Firestore and RTDB are pretty different codebases) and is a broader issue with Xiaomi Shark. Though I'm not able to find other reports out there for this exception on Xiaomi Shark. So I'm not sure what's going on...

Unfortunately I'm not sure how to move this forward. In general you would expect to see this kind of error if there were multiple instances of the app running at once or if you were initializing Firestore (or RTDB) in multiple threads at the same time. I assume that shouldn't be the case for your apps?

The only workaround I can suggest for now is to disable persistence.

If anybody is able to reproduce the issue manually or help narrow down the scope, please let us know!

google-oss-bot commented 4 years ago

Hey @MTermLyo. We need more information to resolve this issue but there hasn't been an update in 7 days. I'm marking the issue as stale and if there are no new updates in the next 3 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot commented 4 years ago

Since there haven't been any recent updates here, I am going to close this issue.

@MTermLyo if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

pupaconnect commented 4 years ago

Caused by java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them. at d.m.d.q.a0.u0.f(com.google.firebase:firebase-firestore@@21.2.1:20) at d.m.d.q.z.s.a(com.google.firebase:firebase-firestore@@21.2.1:18) at d.m.d.q.z.p.run(com.google.firebase:firebase-firestore@@21.2.1:5) at d.m.d.q.e0.a.call(com.google.firebase:firebase-firestore@@21.2.1:1) at d.m.d.q.e0.c$c.a(com.google.firebase:firebase-firestore@@21.2.1:10) at d.m.d.q.e0.f.run(:4) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at d.m.d.q.e0.c$c$b.run(com.google.firebase:firebase-firestore@@21.2.1:3) at java.lang.Thread.run(Thread.java:764)

pupaconnect commented 4 years ago

Caused by java.lang.RuntimeException: java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them. at d.m.d.q.e0.c$c.a(com.google.firebase:firebase-firestore@@21.2.1:13) at d.m.d.q.e0.f.run(:4) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:458) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at d.m.d.q.e0.c$c$b.run(com.google.firebase:firebase-firestore@@21.2.1:3) at java.lang.Thread.run(Thread.java:764)

pupaconnect commented 4 years ago

裝置 品牌: blackshark 型號: Shark 1S 螢幕方向: 縱向 可用 RAM: 2.89 GB 可用磁碟空間: 33.49 GB 作業系統 版本: 9 螢幕方向: 縱向 是否取得 Root 權限: 否 當機 日期: 2019年11月20日 下午12:29:00 應用程式版本: 1.4.6 (46)

narakai commented 4 years ago

I also have encountered this crash on Shark 1S blackshark

MrVilkaman commented 4 years ago

ZTE Blade A0722 (8.1.0) also has crash

HLJheying commented 4 years ago

OPPO F11 (9) hit the same issue

rvgroup commented 4 years ago

Black Shark SKR-H0 (9) also has crash

deputat007 commented 4 years ago

ZTE Blade A0722( 8.1.0)

serrokitskiy commented 4 years ago

Black Shark SKR-H0 also has crash very long time after update to Android 9

shafeekghaseel commented 4 years ago

I got the same crash in Black Shark(9.0) and LG Nexus 5X(6.0.1)

tuantung commented 4 years ago

BlackShark Model: SKR-A0 (9) also has crash 100%

masbae1999 commented 4 years ago

me too, on BlackShark SKR-A0.. Any Solution?

amitabesit commented 4 years ago

Screenshot from 2020-03-15 23-20-36

This issue has 217191 crashes affecting 20663 users - Last 90 days - Dec 17 – Mar 15

  1. Devices - 95% OPPO
  2. Operating systems - 96% Android 9
  3. Device states - 88% background
wilhuff commented 4 years ago

The last summary of this issue was https://github.com/firebase/firebase-android-sdk/issues/953#issuecomment-552054012, wherein we stated that we need your help reproducing this issue. Further stating that this is happening isn't really helping--we definitely understand that this is happening in the wild but don't have any ideas for what could be causing this.

What is your application doing in the background that could be contributing to this?

If you have this kind of device, what steps are you taking to reproduce this issue?

timchanyiuman commented 4 years ago

Recently we also discovered that devices encounter the same exception. We use the following version:

implementation 'com.google.firebase:firebase-firestore:21.3.1'
implementation 'com.google.firebase:firebase-database:19.2.1'

Basically we use the firebase in our background service. In the service's onStartCommand, it will try to init firebase and then registered onDocumentChange event and check any message received from the host. After the message finished poccessing, we will update the status in the map and write it back to the document.

We use ARCA to catch any uncaught exception and found recently the service suffer from the named exception randomly. Sometimes it happened once per few days. Change setPersistenceEnabled(false) also cannot help

Here I post the full source code for your reference:

`/ This service will try to get the message in firebase /

class FirebaseMessageService : Service() { private val tag = "FirebaseMessageService"

private var firebaseDocChangeListener: ListenerRegistration? = null
/**
 * Temporarily save handled task to avoid doing same task more than once
 */
private val localHandledTaskList = mutableListOf<String>()

// private val tmsServiceCheckTimeSecond = 60 * 60L

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {

    Log.d(tag, "onStartCommand")

    firebaseDocChangeListener?.remove()  //remove any existing listener first

    //To test this service, try create a database with
    // SET: messages
    // doc: YOUR_DEVICE_ID (e.g. 7C29509)
    // K,V : message, MESSAGE_YOU_WANT

    val firebaseConfig = PaymentApplication.getTmsConfigV3(true, this).firebase
    initFirebase(firebaseConfig)

    //Use identity as doc name in firebase
    val firebaseDocName = NetworkConfigHelper.getNetworkToken()

    if (firebaseDocName == "") {
        Log.d(tag, "identity null device inactive")
    } else {
        Log.d(tag, "Listen to $firebaseDocName")

        val remotePath = firebaseConfig?.remotePath.orEmpty()
        //make sure firebase initialized
        if (FirebaseApp.getApps(this).any { it.name == remotePath }) {
            //Disable Offline Capabilities
            FirebaseDatabase.getInstance(FirebaseApp.getInstance(remotePath)).setPersistenceEnabled(true)

            firebaseDocChangeListener =
                FirebaseFirestore.getInstance(FirebaseApp.getInstance(remotePath))
                    .collection(remotePath)
                    .document(firebaseDocName)
                    .addSnapshotListener { snapShot: DocumentSnapshot?, firestoreException: FirebaseFirestoreException? ->
                        val isDocumentExists = snapShot?.exists()
                        if (isDocumentExists == true && firestoreException == null) {
                            try {
                                onDocumentChange(remotePath, snapShot, firebaseDocName)
                            } catch (e: Exception) {
                                PaymentLogManager.e(tag, "onDocumentChange exception: $e")
                            }
                        } else {
                            PaymentLogManager.e(tag, "onDocumentChange failed, is document exists: $isDocumentExists, exception: $firestoreException")
                        }
                    }
        }
    }

    return START_STICKY
}

private fun initFirebase(firebaseConfig: FirebaseConfig?) {
    val encryptedString = firebaseConfig?.clientAppKey
    val identity = PaymentApplication.getLocalConfig().identity
    val hashedIdentity = identity.toUpperCase(Locale.ENGLISH).md5()

    val googleServiceJson: JSONObject?
    try {
        googleServiceJson = JSONObject(AesUtils.decrypt(encryptedString, hashedIdentity))
    } catch (e: Exception) {
        PaymentLogManager.e(tag, "fail to get google service json with key $hashedIdentity: $e")
        return
    }

    val projectInfo = googleServiceJson.optJSONObject("project_info")
    val client = ((googleServiceJson.optJSONArray("client")[0] as JSONObject))

    //remove & init again
    FirebaseApp.getApps(this).forEach {
        if (it.name == firebaseConfig?.remotePath.orEmpty()) {
            it.delete()
        }
    }
    FirebaseApp.initializeApp(
        this,
        FirebaseOptions.Builder()
            .setProjectId(projectInfo.optString("project_id"))
            .setDatabaseUrl(projectInfo.optString("firebase_url"))
            .setStorageBucket(projectInfo.optString("storage_bucket"))
            .setApiKey((client.optJSONArray("api_key")[0] as JSONObject).optString("current_key"))
            .setApplicationId(client.optJSONObject("client_info").optString("mobilesdk_app_id"))
            .build(),
        firebaseConfig?.remotePath.orEmpty()
    )

    Log.d(tag, "firebase initialized: ${firebaseConfig?.remotePath.orEmpty()}")
}

private fun onDocumentChange(remotePath: String, snapShot: DocumentSnapshot?, firebaseDocName: String) {
    Log.d(tag, "onDocumentChange: number of actions: ${snapShot?.data?.size}")
    snapShot?.data?.let { map ->
        for ((key, obj) in map) {
            Log.i(tag, "doing task $key")
            if (obj is MutableMap<*, *>) {
                try {
                    val status = obj["status"] as String
                    val action = obj["action"] as String
                    val arg = obj["argument"] as String?

                    if (status == TMSTask.ActionResult.PENDING.toString() && !localHandledTaskList.contains(key)) {
                        localHandledTaskList.add(key)

                        val task = TMSTask(action, arg)
                        val result = task.doAction(this.applicationContext)
                        Log.d(tag, "do action :${task.action} arg:${task.argument} result $result")

                        @Suppress("UNCHECKED_CAST")
                        (obj as MutableMap<String, Any>)["status"] = result.toString()

                        Log.d(tag, "Task finished with result $result")
                        FirebaseFirestore.getInstance(FirebaseApp.getInstance(remotePath))
                            .collection(remotePath)
                            .document(firebaseDocName)
                            .set(map.toMap())
                            .addOnSuccessListener {
                                Log.d(tag, "Update task $key for action status success")
                            }
                            .addOnFailureListener {
                                PaymentLogManager.w(tag, "Update task $key for action status failed: ${it.cause}, ${it.message}")
                            }
                            .addOnCompleteListener {
                                if (localHandledTaskList.contains(key)) {
                                    localHandledTaskList.remove(key)
                                }
                            }
                    } else {
                        Log.d(tag, "task $key already done")
                    }
                } catch (ex: Exception) {
                    PaymentLogManager.w(tag, "error during parsing task $key")
                }
            } else {
                PaymentLogManager.w(tag, "key $key value unknown format $obj")
            }
        }
    }
}

override fun onBind(intent: Intent?): IBinder? {
    return null
}

}`

ChristBKK commented 4 years ago

Having the same crashes on multiple devices

raunak500 commented 4 years ago

Even i am facing the same issue on Realme 1 and Realme 2 pro. I am accessing the firestore using a thread safe approach.

public static synchronized FirebaseFirestore getmFirestore() { if (mFirestore == null) { FirebaseFirestoreSettings.Builder firebaseFirestoreSettingsBuilder = new FirebaseFirestoreSettings.Builder(); firebaseFirestoreSettingsBuilder.setPersistenceEnabled(true); mFirestore = FirebaseFirestore.getInstance(); mFirestore.setFirestoreSettings(firebaseFirestoreSettingsBuilder.build()); } return mFirestore; }

Did anyone come to know the root cause for this?

zhangjizxc commented 4 years ago

image Have the same issue. How to do a workaround?

brunogabriel commented 4 years ago

Anyone find a solution for this problem? Here just Blackshark with this problem, we're using version 21.4.2

google-oss-bot commented 3 years ago

Hey @MTermLyo. We need more information to resolve this issue but there hasn't been an update in 5 weekdays. I'm marking the issue as stale and if there are no new updates in the next 5 days I will close it automatically.

If you have more information that will help us get to the bottom of this, just add a comment!

google-oss-bot commented 3 years ago

Since there haven't been any recent updates here, I am going to close this issue.

@MTermLyo if you're still experiencing this problem and want to continue the discussion just leave a comment here and we are happy to re-open this.

DAKSHSEMWAL commented 3 years ago

Happening with us too.

DAKSHSEMWAL commented 3 years ago

E/AndroidRuntime: FATAL EXCEPTION: main Process: me.dozee.dozee.debug, PID: 25221 java.lang.RuntimeException: Internal error in Cloud Firestore (21.3.1). at com.google.firebase.firestore.util.AsyncQueue.lambda$panic$3(com.google.firebase:firebase-firestore@@21.3.1:529) at com.google.firebase.firestore.util.AsyncQueue$$Lambda$3.run(Unknown Source:2) at android.os.Handler.handleCallback(Handler.java:900) at android.os.Handler.dispatchMessage(Handler.java:103) at android.os.Looper.loop(Looper.java:219) at android.app.ActivityThread.main(ActivityThread.java:8349) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055) Caused by: java.lang.RuntimeException: java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them. at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1(com.google.firebase:firebase-firestore@@21.3.1:320) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run(Unknown Source:4) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(com.google.firebase:firebase-firestore@@21.3.1:224) at java.lang.Thread.run(Thread.java:929) Caused by: java.lang.RuntimeException: Failed to gain exclusive lock to the Cloud Firestore client's offline persistence. This generally means you are using Cloud Firestore from multiple processes in your app. Keep in mind that multi-process Android apps execute the code in your Application class in all processes, so you may need to avoid initializing Cloud Firestore in your Application class. If you are intentionally using Cloud Firestore from multiple processes, you can only enable offline persistence (that is, call setPersistenceEnabled(true)) in one of them. at com.google.firebase.firestore.local.SQLitePersistence.start(com.google.firebase:firebase-firestore@@21.3.1:132) at com.google.firebase.firestore.core.FirestoreClient.initialize(com.google.firebase:firebase-firestore@@21.3.1:269) at com.google.firebase.firestore.core.FirestoreClient.lambda$new$0(com.google.firebase:firebase-firestore@@21.3.1:108) at com.google.firebase.firestore.core.FirestoreClient$$Lambda$1.run(Unknown Source:8) at com.google.firebase.firestore.util.AsyncQueue.lambda$enqueue$2(com.google.firebase:firebase-firestore@@21.3.1:431) at com.google.firebase.firestore.util.AsyncQueue$$Lambda$2.call(Unknown Source:2) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor.lambda$executeAndReportResult$1(com.google.firebase:firebase-firestore@@21.3.1:317) at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$$Lambda$2.run(Unknown Source:4)  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)  at java.util.concurrent.FutureTask.run(FutureTask.java:266)  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:301)  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)  at com.google.firebase.firestore.util.AsyncQueue$SynchronizedShutdownAwareExecutor$DelayedStartFactory.run(com.google.firebase:firebase-firestore@@21.3.1:224)  at java.lang.Thread.run(Thread.java:929)  Caused by: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (Sqlite code 5 SQLITE_BUSY), (OS error - 2:No such file or directory) at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method) at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:692) E/AndroidRuntime: at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:335) at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:310) at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:594) at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:504) at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:428) at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:332) at com.google.firebase.firestore.local.SQLitePersistence.start(com.google.firebase:firebase-firestore@@21.3.1:129) ... 14 more