amplify-android
amplify-android copied to clipboard
SQLiteDatabaseLockedException caused by TransferDBHelper.update$aws_storage_s3_release
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
Language and Async Model
Java
Amplify Categories
Storage
Gradle script dependencies
// Put output below this line
implementation "com.amplifyframework:core:2.14.10"
implementation "com.amplifyframework:aws-storage-s3:2.14.10"
implementation "com.amplifyframework:aws-auth-cognito:2.14.10"
Environment information
# Put output below this line
------------------------------------------------------------
Gradle 8.2
------------------------------------------------------------
Build time: 2023-06-30 18:02:30 UTC
Revision: 5f4a070a62a31a17438ac998c2b849f4f6892877
Kotlin: 1.8.20
Groovy: 3.0.17
Ant: Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM: 17.0.10 (MacPorts 17.0.10+11)
OS: Mac OS X 14.3 x86_64
Please include any relevant guides or documentation you're referencing
No response
Describe the bug
Hi there!
We have a few reports (about 20 at the moment) on Firebase with this crash for a few latest releases of the library v2.14.x including the last one v2.14.10. The issue appears on Android 10-13, affected devices are mostly Motorola (around 80%) with some Samsung, Xiaomi etc.
The issue is quite rare and, unfortunately, there are no exact steps to reproduce it. I don't see any specific pattern in accompanying logs. Sometimes it happened after the app update, but in the minority of the cases.
Reproduction steps (if applicable)
No response
Code Snippet
// Initialization in Application class
Amplify.Logging.disable();
Amplify.addPlugin(new AWSCognitoAuthPlugin());
Amplify.addPlugin(new AWSS3StoragePlugin());
AmplifyConfiguration amplifyConfig = AmplifyConfiguration.builder(context)
.devMenuEnabled(false)
.build();
Amplify.configure(amplifyConfig, context);
// Uploading, somewhere in the app
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Map<String, String> metadata = new ArrayMap<>(4);
metadata.put("date", dateFormat.format(date));
metadata.put("session_uuid", uid);
metadata.put("token", authToken);
metadata.put("service", serviceName);
StorageUploadFileOptions options =
StorageUploadFileOptions.builder()
.accessLevel(StorageAccessLevel.PUBLIC)
.contentType(mimeType)
.metadata(metadata)
.build();
final File file = new File(path);
if (file.canRead()) {
Amplify.Storage.uploadFile(
file.getName(),
file,
options,
result -> {
// write success logs
},
failure -> {
// write failure logs
}
);
}
Log output
// Put your logs below this line
Fatal Exception: android.database.sqlite.SQLiteDatabaseLockedException
database is locked (code 5 SQLITE_BUSY)
android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount (SQLiteConnection.java)
android.database.sqlite.SQLiteConnection.executeForChangedRowCount (SQLiteConnection.java:900)
android.database.sqlite.SQLiteSession.executeForChangedRowCount (SQLiteSession.java:756)
android.database.sqlite.SQLiteStatement.executeUpdateDelete (SQLiteStatement.java:66)
android.database.sqlite.SQLiteDatabase.updateWithOnConflict (SQLiteDatabase.java:1817)
android.database.sqlite.SQLiteDatabase.update (SQLiteDatabase.java:1763)
com.amplifyframework.storage.s3.transfer.TransferDBHelper.update$aws_storage_s3_release (TransferDBHelper.kt:192)
com.amplifyframework.storage.s3.transfer.TransferDB.updateState (TransferDB.kt:215)
com.amplifyframework.storage.s3.transfer.TransferStatusUpdater.updateTransferState (TransferStatusUpdater.kt:106)
com.amplifyframework.storage.s3.transfer.TransferWorkerObserver.updateTransferState (TransferWorkerObserver.kt:166)
com.amplifyframework.storage.s3.transfer.TransferWorkerObserver.handleTransferStatusUpdate (TransferWorkerObserver.kt:116)
com.amplifyframework.storage.s3.transfer.TransferWorkerObserver.access$handleTransferStatusUpdate (TransferWorkerObserver.kt:35)
com.amplifyframework.storage.s3.transfer.TransferWorkerObserver$onChanged$1.invokeSuspend (TransferWorkerObserver.kt:95)
kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith (ContinuationImpl.kt:33)
kotlinx.coroutines.DispatchedTask.run (DispatchedTask.kt:108)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
java.lang.Thread.run (Thread.java:923)
amplifyconfiguration.json
No response
GraphQL Schema
// Put your schema below this line
Additional information and screenshots
No response
Hello thanks for reporting this issue. Someone from our team will take look at this.
🤔 This error suggests that there may be concurrent SQliteOpenHelper
instances access the database. We will need to look into how that might be possible.
Hi guys!
I just want to give you some additional context. For the last 30 days this issue was registered for 9 users in Firebase.
The issue appears on Android 7-13, affected devices are Samsung (S10, A13, Galaxy A72), Sony (Xperia 8), Motorola (Moto G Pure), Xiaomi (Redmi 5), Oppo, LG.
The stack trace is the same for all cases, except for some cases the cause is "database is locked (code 5 SQLITE_BUSY)" and for others it's "database is locked (code 5 SQLITE_BUSY[5])".
AWS Amplify v2.14.11
Thanks for the update @yaroslav-v.
I've spent a little while looking at this and I'm not quite sure how this error is occurring. Although the TransferDB.getInstance
function is not thread-safe, we still should not be creating multiple instances as it's only created once per TransferManager
, which is once per plugin.
@yaroslav-v just for confirmation: you're not creating multiple instances of AWSS3StoragePlugin
, right? One way this can happen is if your application manifest has any android:process
tags to make different components run in their own processes.
Barring that, I think my plan for this issue will to be to clean up the creation of the TransferDB
to make it thread safe and see if that makes any difference. I'm not expecting that to resolve the issue, but it can't hurt.
@mattcreaser Hi! Thx for trying.
I've double checked and there are no android:process
in the manifest and Amplify.addPlugin(new AWSS3StoragePlugin());
is called only from the application extension class.
Oops after looking at it again this morning I realized I missed the obvious bug in the implementation of the singleton pattern for TransferDB
. I'll make a fix today.
This fix has been released in Amplify 2.15.2 🎉
Closing this issue, please feel free to open a new one if required.
This issue is now closed. Comments on closed issues are hard for our team to see. If you need more assistance, please open a new issue that references this one.