Description
Expected Behavior
Want to known which scenes will occurrenced. So i can do something.
Actual Behavior
My project is an multipule processes application.
Used android-database-sqlcipher(4.5.1) and androidx.room(2.2.0).
Each process open an database on singleInstance.
This crash was occurrenced by stability monkey test, and on firebase also has few this crash.I can't reproduce this crash by normal operation.
Our JournalMode set JournalMode.TRUNCATE forced.
On our code,we retry beginTransaction when accept SQLiteDatabaseException(message is startwith database is locked).
boolean retry;
int tryCount = 0;
do {
retry = false;
try {
if (withListener) {
mDelegate.beginTransactionWithListener(transactionListener);
} else {
mDelegate.beginTransaction();
}
if (DEBUG && tryCount > 0) {
Log.d(TAG, "beginTransactionSafely()-> tryCount = " + tryCount);
}
} catch (SQLiteException exception) {
String message = exception.getMessage();
if (message != null && message.startsWith("database is locked")) {
if (DEBUG) {
Log.d(TAG, "beginTransactionSafely()-> " + message);
}
long sleepTime = Math.min(160, (tryCount + 1) * 20);
SystemClock.sleep(sleepTime);
tryCount++;
retry = true;
} else {
throw exception;
}
}
} while (retry);
Steps to Reproduce
I query sqlite doc how problem occur.But nothing get.
Also i read sqlite source code, but i can't understander all code. Only i can known is sqlite3_step() return SQLite_OK but not SQLite_Done. I don't known why return SQLite_OK and which scenes occurrence.
SQLCipher version (can be identified by executing PRAGMA cipher_version;
):
4.5.1 community
SQLCipher for Android version:
4.5.1
Crash Stack
Build Info: 'unknown:alps-mp-q0.mp1-V3_reallytek.q0mp1.k61v1.64.bsp_P93:mt6761:S01,TECNO/H624/TECNO-KB8:10/QP1A.190711.020/BNPQ-201230V852:user/release-keys'
MSSI Info: 'TECNO/H624/TECNO-KB8:10/QP1A.190711.020/BNPQ-201230V852:user/release-keys'
Exception Log Time:[Tue Oct 11 13:43:41 WAT 2022] [7593.371736]
Exception Class: Java (JE)
Exception Type: system_app_crash
Current Executing Process:
net.bat.store
net.bat.store v2911 (V5.1.39.11)
Trigger time:[2022-10-11 13:43:41.357436] pid:11587
Backtrace:
Process: net.bat.store
PID: 11587
UID: 10064
Flags: 0x38d83ec5
Package: net.bat.store v2911 (V5.1.39.11)
Foreground: Yes
Build: TECNO/H624/TECNO-KB8:10/QP1A.190711.020/BNPQ-201230V852:user/release-keys
net.sqlcipher.database.SQLiteException: not an error: BEGIN EXCLUSIVE;
at net.sqlcipher.database.SQLiteDatabase.native_execSQL(Native Method)
at net.sqlcipher.database.SQLiteDatabase.execSQL(SourceFile:4)
at net.sqlcipher.database.SQLiteDatabase.beginTransactionWithListenerInternal(SourceFile:8)
at net.sqlcipher.database.SQLiteDatabase.beginTransactionWithListener(SourceFile:1)
at net.sqlcipher.database.SQLiteDatabase.beginTransaction(SourceFile:1)
at net.bat.store.datamanager.db.AhaSupportSQLiteDatabase.beginTransactionSafely(SourceFile:2)
at net.bat.store.datamanager.db.AhaSupportSQLiteDatabase.beginTransaction(SourceFile:1)
at androidx.room.RoomDatabase.beginTransaction(SourceFile:4)
at net.bat.store.datamanager.dao.GameDao_Impl.insertOrIgnoreGame(SourceFile:2)
at net.bat.store.datamanager.server.GameDaoImpl.insertOrIgnoreGame(SourceFile:1)
at net.bat.store.datamanager.client.proxy.GameDaoProxy.insertOrIgnoreGame(SourceFile:1)
at net.bat.store.runtime.util.OpenGame$1.run(SourceFile:1)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at net.bat.store.thread.BaseThreadPoolExecutor$BaseThreadFactory.lambda$newThread$0(SourceFile:2)
at net.bat.store.thread.-$$Lambda$BaseThreadPoolExecutor$BaseThreadFactory$lEX5z4jVWLqetPCsXEvyDjhH5Vg.run(Unknown Source:2)
at java.lang.Thread.run(Thread.java:919)
MyCode
GameDao_Impl.java
public void insertOrIgnoreGame(final GameTable gameTable) {
__db.assertNotSuspendingTransaction();
__db.beginTransaction();
try {
__insertionAdapterOfGameTable_1.insert(gameTable);
__db.setTransactionSuccessful();
} finally {
__db.endTransaction();
}
}
AhaSupportSQLiteDatabase.java
public void beginTransaction() {
beginTransactionSafely(false, null);
}
private void beginTransactionSafely(boolean withListener, SQLiteTransactionListener transactionListener) {
boolean retry;
int tryCount = 0;
do {
retry = false;
try {
if (withListener) {
mDelegate.beginTransactionWithListener(transactionListener);
} else {
mDelegate.beginTransaction();
}
if (DEBUG && tryCount > 0) {
Log.d(TAG, "beginTransactionSafely()-> tryCount = " + tryCount);
}
} catch (SQLiteException exception) {
String message = exception.getMessage();
if (message != null && message.startsWith("database is locked")) {
if (DEBUG) {
Log.d(TAG, "beginTransactionSafely()-> " + message);
}
long sleepTime = Math.min(160, (tryCount + 1) * 20);
SystemClock.sleep(sleepTime);
tryCount++;
retry = true;
} else {
throw exception;
}
}
} while (retry);
}
I can provider all stability log if you need!