Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

closeAndUnregister makes a thread local transaction manager completely dead #1476

Closed
Kaned1as opened this issue Mar 17, 2022 · 1 comment
Closed

Comments

@Kaned1as
Copy link

After using TransactionManager.closeAndUnregister(db) the thread becomes completely unusable for using any other database.

Approximate reproduction steps:

  1. Make a database through Database.connect() in main thread
  2. Use this database in a thread pool (threads 1, 2, 3)
  3. Use TransactionManager.closeAndUnregister in last task (let's say, thread 1)
  4. Now create another database through Database.connect() in main thread
  5. Try to use this new database through the thread 1 of thread pool

This is what you get:

java.lang.IllegalStateException: Please call Database.connect() before using this code
	at org.jetbrains.exposed.sql.transactions.NotInitializedManager.currentOrNull(TransactionApi.kt:38) ~[exposed-core-0.37.3.jar!/:na]
	at org.jetbrains.exposed.sql.transactions.TransactionManager$Companion.currentOrNull(TransactionApi.kt:108) ~[exposed-core-0.37.3.jar!/:na]
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$transaction$1.invoke(ThreadLocalTransactionManager.kt:136) ~[exposed-core-0.37.3.jar!/:na]
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:223) ~[exposed-core-0.37.3.jar!/:na]
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:135) ~[exposed-core-0.37.3.jar!/:na]
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:132) ~[exposed-core-0.37.3.jar!/:na]
@Kaned1as
Copy link
Author

Kaned1as commented Mar 17, 2022

I'll provide a bit more context.

In TransactionManager.closeAndUnregister there is following statement:

val manager = registeredDatabases[database]
manager?.let {
    registeredDatabases.remove(database)
    databases.remove(database)
    currentDefaultDatabase.compareAndSet(database, null)
    if (currentThreadManager.get() == it) { // <-------- this one
        currentThreadManager.remove()
    }
}

it calls currentThreadManager.get(). If current thread has this thread local removed (very common situation when there's no current transaction), it will try to re-initialize it. And will fail, because both databases and registeredDatabases are empty now, so it will default to NotInitializedManager, which will stick and destroy any transaction(...) call that you may try in this thread afterwards.

Wrapping it into transaction(...) won't help, it will fail to finish transaction as there won't be any databases/managers left after the closeAndUnregister call.

@Kaned1as Kaned1as changed the title closeAndUnregister somehow makes a thread local transaction manager completely dead closeAndUnregister makes a thread local transaction manager completely dead Mar 17, 2022
@Tapac Tapac closed this as completed Apr 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants