Reputation: 1764
I want to simulate android.database.CursorWindowAllocationException
crash. I am working on a huge codebase with a lot of room database queries in each screen. I am not sure in which database query this crash occurs and in which scenario this crash occurs. So is there any way to simulate
this crash? I tried keeping almost 10 database cursors
open in a for loop but could not reproduce the crash. I have attached the crashlytics
logs for reference.
Fatal Exception: android.database.CursorWindowAllocationException: Cursor window allocation of 2048 kb failed.
at android.database.CursorWindow.<init>(CursorWindow.java:108)
at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:198)
at android.database.sqlite.SQLiteCursor.clearOrCreateWindow(SQLiteCursor.java:309)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:141)
at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:220)
at android.database.AbstractCursor.moveToNext(AbstractCursor.java:269)
at androidx.room.InvalidationTracker$1.checkUpdatedTable(InvalidationTracker.java:461)
at androidx.room.InvalidationTracker$1.run(InvalidationTracker.java:431)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
Upvotes: 0
Views: 930
Reputation: 56928
The following simulates such a crash (but traps it):-
var lastIndex = 0
try
{
for (i in 0..1999) {
lastIndex = i
val csr: Cursor = db.openHelper.writableDatabase.query(SimpleSQLiteQuery("SELECT * FROM model"))
val count = csr.count.toLong()
}
}catch ( e:java.lang.Exception)
{
Log.d(
"DBEXCEPTION",
"Exception trapped at INDEX " + lastIndex + " Message was " + e.message
)
e.printStackTrace()
}
}
db
is an instance of an @Database
annotated class (etc).csr.count.toLong
The log will then contain something like:-
2022-09-20 09:48:01.929 E/CursorWindow: CursorWindow: mmap() failed: errno=12.
2022-09-20 09:48:01.930 D/DBEXCEPTION: Exception trapped at INDEX 1415 Message was Could not allocate CursorWindow '/data/user/0/a.a.so73757679kotlinroomuniqueconflict/databases/the_database.db' of size 2097152 due to error -12.
2022-09-20 09:48:01.930 W/System.err: android.database.CursorWindowAllocationException: Could not allocate CursorWindow '/data/user/0/a.a.so73757679kotlinroomuniqueconflict/databases/the_database.db' of size 2097152 due to error -12.
2022-09-20 09:48:01.930 W/System.err: at android.database.CursorWindow.nativeCreate(Native Method)
2022-09-20 09:48:01.930 W/System.err: at android.database.CursorWindow.<init>(CursorWindow.java:139)
2022-09-20 09:48:01.930 W/System.err: at android.database.CursorWindow.<init>(CursorWindow.java:120)
2022-09-20 09:48:01.930 W/System.err: at android.database.AbstractWindowedCursor.clearOrCreateWindow(AbstractWindowedCursor.java:202)
2022-09-20 09:48:01.931 W/System.err: at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:147)
2022-09-20 09:48:01.931 W/System.err: at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:140)
2022-09-20 09:48:01.931 W/System.err: at android.app.Activity.performCreate(Activity.java:7994)
2022-09-20 09:48:01.931 W/System.err: at android.app.Activity.performCreate(Activity.java:7978)
2022-09-20 09:48:01.931 W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
2022-09-20 09:48:01.931 W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3422)
2022-09-20 09:48:01.931 W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3601)
2022-09-20 09:48:01.931 W/System.err: at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:85)
2022-09-20 09:48:01.931 W/System.err: at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
2022-09-20 09:48:01.931 W/System.err: at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
2022-09-20 09:48:01.931 W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2066)
2022-09-20 09:48:01.932 W/System.err: at android.os.Handler.dispatchMessage(Handler.java:106)
2022-09-20 09:48:01.932 W/System.err: at android.os.Looper.loop(Looper.java:223)
2022-09-20 09:48:01.932 W/System.err: at android.app.ActivityThread.main(ActivityThread.java:7656)
2022-09-20 09:48:01.932 W/System.err: at java.lang.reflect.Method.invoke(Native Method)
2022-09-20 09:48:01.932 W/System.err: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
2022-09-20 09:48:01.932 W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-09-20 09:48:02.003 W/libc: malloc(4194304) failed: returning null pointer
2022-09-20 09:48:02.003 A/libc: Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x80000 in tid 23176 (RenderThread), pid 23153 (muniqueconflict)
It should be noted that the issue at hand is not exactly the number of Cursors but that underlying a Cursor is a file and that (I believe) the issue is the number of unclosed file allocations of which the database itself will have 3 (for the database, the -wal file and the -shm file).
However, there may also be a memory related issue, as this test then results in the malloc error (failed to get 4Mb).
Upvotes: 1