Completed
Details
Assignee
Sean CorfieldSean CorfieldReporter
Rogan MorrowRogan MorrowPriority
Minor
Details
Details
Assignee
Sean Corfield
Sean CorfieldReporter
Rogan Morrow
Rogan MorrowPriority
Created October 6, 2016 at 7:57 AM
Updated March 1, 2017 at 6:55 PM
Resolved March 1, 2017 at 6:55 PM
In `clojure.java.jdbc`, it is possible for the function `get-connection` to call `clojure.lang.RT/loadClassForName` on the driver's classname. JDBC drivers have a static initializer to register themselves with `java.sql.DriverManager` upon load. However, `DriverManager`, as part of its static initializer, loads every implementation of `Driver` on the classpath. This causes an insidious bug when trying to use JDBC from two separate threads where each thread is using a different driver.
For example, if thread A tries to call `get-connection` with a db-spec using driver X, and thread B tries to call `get-connection` with a db-spec using driver Y, then thread A will load driver X which in turn loads `DriverManager`, which again in turn tries to load all drivers on the classpath, including driver Y. If driver Y is simultaneously being loaded by thread B, then driver Y will be trying to load `DriverManager` which is trying to load driver Y, thus creating deadlock. This behaviour can be reliably reproduced using the Clojure files attached.
I am not sure if this is even the responsibility of JDBC to fix. If you want to patch it on the JDBC side, it is easily possible to do so by making sure `DriverManager` is loaded before trying to load the driver.