Skip to content

java.util.concurrent.TimeoutException: net.sqlcipher.database.SQLiteCompiledSql.finalize() timed out after 10 seconds #537

Closed
@oleksandr-semenov

Description

@oleksandr-semenov

Expected Behavior

App doesn't crash

Actual Behavior

App crashes due to SQLiteCipher on Android API 24-25

Steps to Reproduce

App uses Room + SQLCipher.
WAL is enabled.

The only synthetic case how I can emulate crash is accessing SQLiteCompiledSql(Use API 24-25 Android emulator):

  1. Launch thread A
  2. Launch thread B
  3. Block B, In A create SQLiteCompiledSql object, set nStatement so that finalize can run releaseSqlStatement, block A, unblock B
  4. In B launch start a long transaction, unblock A, do memory extensive work to cause GC
  5. Wait

Android test Kotlin code(if required I can convert to Java):

  @Test
    fun emulateCrash() = coroutineRule.runBlocking {
        dbRule.useWithProject {
            val latch1 = CountDownLatch(1)
            val latch2 = CountDownLatch(1)

            launch (Dispatchers.IO) {
                SQLiteProxy(db.openHelper.writableDatabase as SQLiteDatabase, "SELECT 1 FROM Album").setupStub()
                latch2.countDown()
                latch1.await()
            }

            latch2.await()
            db.withTransaction {
                latch1.countDown()
                while (true) {
                    // no matter what  - just pollute memory to cause GC
                    val albumEntity = newAlbum(
                        projectEntity = projectEntity,
                        companyEntity = companyEntity
                    )
                }
            }
        }
    }
package net.sqlcipher.database;

public class SQLiteProxy extends SQLiteCompiledSql {

    public SQLiteProxy(SQLiteDatabase db, String sql) {
        super(db, sql);
    }

    public void setupStub() {
        nStatement = Long.MAX_VALUE;
    }

}

SQLCipher version (can be identified by executing PRAGMA cipher_version;):
4.4.2 community

SQLCipher for Android version:
4.4.2

Room version:
2.3.0-beta01

My guess would be how Android handles GC and especially finalize() on version API 24-25.
Since there is DB lock() call that blocks/await thread this causes watchdog to throw exception.
I've checked generated Room code and I don't see where the cursor can be not closed.
Not sure when the compiled statement is not cached to emulate the scenario.
However, it happens in normal code execution with extensive concurrent work and multiple transactions.

Can releaseSqlStatement be removed from finalize or handled in a different way?

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-detailsNeeds additional details to proceed.staleThis issue lacks recent activity.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions