diff --git a/testprocess/TestItemServer/src/TestItemServer.jl b/testprocess/TestItemServer/src/TestItemServer.jl index 5b6c69e..447976d 100644 --- a/testprocess/TestItemServer/src/TestItemServer.jl +++ b/testprocess/TestItemServer/src/TestItemServer.jl @@ -1089,6 +1089,34 @@ function activate_env_request(params::TestItemServerProtocol.ActivateEnvParams, TestEnv.activate(params.packageName) end + # The controller serializes this request: one test process is nominated to activate + # while every other one waits, and they are released when it reports back. The point + # of that is to build the test environment's precompile caches exactly once, because + # Julia has no cache file locking before 1.10 — two processes precompiling the same + # package race, and on Windows the loser cannot replace a `.ji` the winner holds + # open, so it dies with "Cannot write cache file". + # + # From Julia 1.9 on, `TestEnv.activate` finishes with `Pkg._auto_precompile` on the + # sandbox environment, so the caches really are built inside that window. The older + # variants stop at `Pkg.activate`, and `Pkg.instantiate` did not precompile before + # Julia 1.6 either — so nothing was compiled until the first `using` inside a test + # item, which happens in every test process at once, after the gate has let them all + # go. Precompiling here puts that work back inside the serialized window. + @static if VERSION < v"1.9" + try + # `Pkg.precompile` does not exist before Julia 1.4 — it only became a + # forwarder to `Pkg.API.precompile` then, and before that the name resolved + # to `Base.precompile` through the implicit `using Base` and threw a + # MethodError. `Pkg.API.precompile()` has a zero-argument method in every + # version this branch runs on. + Pkg.API.precompile() + catch err + # Not worth failing activation over: whatever is wrong will come back with a + # better message when a test item loads the package. + @debug "Precompiling the test environment failed" exception = (err, catch_backtrace()) + end + end + return TestItemServerProtocol.ActivateEnvResult( status = "success", error = missing