sqlite-jdbc icon indicating copy to clipboard operation
sqlite-jdbc copied to clipboard

Possible race condition in SQLitePooledConnection

Open nicolatimeus opened this issue 3 years ago • 6 comments

Hi all,

I've noticed that at https://github.com/xerial/sqlite-jdbc/blob/3904e83bf0b2e9d9ab2019f8c8bf49f567fb74ac/src/main/java/org/sqlite/javax/SQLitePooledConnection.java#L106

the ConnectionEventListener.connectionClosed() method is called and then the subsequent lines may perform modifications on the released connection:

https://github.com/xerial/sqlite-jdbc/blob/3904e83bf0b2e9d9ab2019f8c8bf49f567fb74ac/src/main/java/org/sqlite/javax/SQLitePooledConnection.java#L110

https://github.com/xerial/sqlite-jdbc/blob/3904e83bf0b2e9d9ab2019f8c8bf49f567fb74ac/src/main/java/org/sqlite/javax/SQLitePooledConnection.java#L112

Should these modifications be moved before the invocation of ConnectionEventListener.connectionClosed()? Otherwise the client code may start reusing the released connection concurrently while they are being performed.

nicolatimeus avatar Dec 20 '22 15:12 nicolatimeus

Would you be able to provide an example project or unit test that would highlight the problem maybe ?

gotson avatar Dec 21 '22 05:12 gotson

Sure, I have created the following project:

https://github.com/nicolatimeus/sqlite-test/blob/main/src/main/java/com/github/nicolatimeus/App.java

On my machine execution stops after a few iterations with exceptions like the following:

org.sqlite.SQLiteException: [SQLITE_ERROR] SQL error or missing database (cannot rollback - no transaction is active)
        at org.sqlite.core.DB.newSQLException(DB.java:1135)
        at org.sqlite.core.DB.newSQLException(DB.java:1146)
        at org.sqlite.core.DB.throwex(DB.java:1106)
        at org.sqlite.core.DB.exec(DB.java:198)
        at org.sqlite.SQLiteConnection.rollback(SQLiteConnection.java:455)
        at org.sqlite.javax.SQLitePooledConnection$1.invoke(SQLitePooledConnection.java:110)
        at com.sun.proxy.$Proxy0.close(Unknown Source)
        at com.github.nicolatimeus.App.worker(App.java:71)
        at com.github.nicolatimeus.App.lambda$0(App.java:94)
        at java.lang.Thread.run(Thread.java:748)

nicolatimeus avatar Dec 22 '22 14:12 nicolatimeus

Thanks, i have the same error on my machine, and managed to set your sample as a unit test. I'm not sure about the fix though.

Should these modifications be moved before the invocation of ConnectionEventListener.connectionClosed()? Otherwise the client code may start reusing the released connection concurrently while they are being performed.

This doesn't fix the issue.

gotson avatar Jan 04 '23 07:01 gotson

Thank you for testing this out.

I'm experimenting with change [1] that seems to fix the issue for me, other than reordering the statements in the close method I have added an extra check to avoid running the close logic twice during SQLitePooledConnection.getConnection().

[1] https://github.com/nicolatimeus/sqlite-jdbc/commit/6a0de0a666f30edd049a97db8ced47d54b60d099

nicolatimeus avatar Jan 09 '23 09:01 nicolatimeus

@gotson any news on that ?

salvatore-coppola avatar Jan 17 '23 14:01 salvatore-coppola

@gotson any news on that ?

I am not working on this, PRs are welcome.

gotson avatar Jan 18 '23 03:01 gotson