Possible race condition in SQLitePooledConnection
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.
Would you be able to provide an example project or unit test that would highlight the problem maybe ?
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)
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.
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
@gotson any news on that ?
@gotson any news on that ?
I am not working on this, PRs are welcome.