Closed mfikes closed 5 years ago
Recently I haven't been able to repro this. Perhaps something has changed that rectified it.
This still crops up occasionally, so I did some more digging. I believe what is happening is the following:
lein-monolith
is running a higher-order each
task with the :parallel
option, it constructs a thread pool and calls apply-subproject-task
on each project as the upstream projects complete.init-project
is called to prepare the project for the task execution, then resolve-and-apply-task
to run the task in the project.activate-middleware
which is responsible for (among other things) loading plugin hooks with load-hooks
.require-resolve
utility, which predates the requiring-resolve
core function added in Clojure 1.10.require-resolve
function first checks whether the namespace of the symbol exists and is loaded before it resolves the symbol, requiring it if not.require
ultimately calls load-lib
which uses clojure.lang.RT/load
under the hood. That does a bunch of stuff, but importantly the loads aren’t synchronized across threads.lein-environ
is not loaded yet, and two projects using it get run in parallel. Both of them try to load the plugin hooks, one of them goes first and starts compiling the namespace, while the other one sees that the namespace exists and resolves the var before it’s been fully defined.Clojure 1.10 added a new serialized-require
function which is used internally by requiring-resolve
, which would address this problem. However, Leiningen is probably not ready to require Clojure 1.10 features, so we'll need to figure out a way to lock appropriately within lein-monolith to fix this.
When running
it was progressing through the topo graph building and when
it encountered an error
I tried again without
:parallel
and it succeeded. Trying again with:parallel
caused it to recur, so perhaps it is relatively reproducible.I'm using 0.3.0: