diff --git a/base/loading.jl b/base/loading.jl index f0eb80f588f368..08c96e2d6bf1f7 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -460,7 +460,9 @@ the form `pkgversion(@__MODULE__)` can be used. function pkgversion(m::Module) rootmodule = moduleroot(m) pkg = PkgId(rootmodule) - pkgorigin = get(pkgorigins, pkg, nothing) + pkgorigin = @lock require_lock begin + get(pkgorigins, pkg, nothing) + end return pkgorigin === nothing ? nothing : pkgorigin.version end @@ -952,8 +954,8 @@ function _tryrequire_from_serialized(modkey::PkgId, build_id::UInt64) try modpath = locate_package(modkey) modpath === nothing && return nothing + set_pkgorigin_version_path(modkey, String(modpath)) loaded = _require_search_from_serialized(modkey, String(modpath), build_id) - get!(PkgOrigin, pkgorigins, modkey).path = modpath finally loading = pop!(package_locks, modkey) notify(loading, loaded, all=true) @@ -971,7 +973,7 @@ end # loads a precompile cache file, ignoring stale_cachefile tests # assuming all depmods are already loaded and everything is valid -function _tryrequire_from_serialized(modkey::PkgId, path::String, depmods::Vector{Any}) +function _tryrequire_from_serialized(modkey::PkgId, path::String, sourcepath::String, depmods::Vector{Any}) assert_havelock(require_lock) loaded = nothing if root_module_exists(modkey) @@ -992,6 +994,7 @@ function _tryrequire_from_serialized(modkey::PkgId, path::String, depmods::Vecto end package_locks[modkey] = Threads.Condition(require_lock) try + set_pkgorigin_version_path(modkey, sourcepath) loaded = _include_from_serialized(modkey, path, depmods) finally loading = pop!(package_locks, modkey) @@ -1059,7 +1062,7 @@ end continue end modstaledeps = modstaledeps::Vector{Any} - staledeps[i] = (modkey, modpath_to_try, modstaledeps) + staledeps[i] = (modpath, modkey, modpath_to_try, modstaledeps) modfound = true break end @@ -1081,8 +1084,8 @@ end for i in 1:length(staledeps) dep = staledeps[i] dep isa Module && continue - modkey, modpath_to_try, modstaledeps = dep::Tuple{PkgId, String, Vector{Any}} - dep = _tryrequire_from_serialized(modkey, modpath_to_try, modstaledeps) + modpath, modkey, modpath_to_try, modstaledeps = dep::Tuple{String, PkgId, String, Vector{Any}} + dep = _tryrequire_from_serialized(modkey, modpath_to_try, modpath, modstaledeps) if !isa(dep, Module) @debug "Rejecting cache file $path_to_try because required dependency $modkey failed to load from cache file for $modpath." exception=dep staledeps = true @@ -1321,7 +1324,9 @@ function unreference_module(key::PkgId) end end +# whoever takes the package_locks[pkg] must call this function immediately function set_pkgorigin_version_path(pkg, path) + assert_havelock(require_lock) pkgorigin = get!(PkgOrigin, pkgorigins, pkg) if path !== nothing project_file = locate_project_file(joinpath(dirname(path), "..")) @@ -1334,6 +1339,7 @@ function set_pkgorigin_version_path(pkg, path) end end pkgorigin.path = path + nothing end # Returns `nothing` or the new(ish) module @@ -1353,13 +1359,13 @@ function _require(pkg::PkgId) toplevel_load[] = false # perform the search operation to select the module file require intends to load path = locate_package(pkg) - set_pkgorigin_version_path(pkg, path) if path === nothing throw(ArgumentError(""" Package $pkg is required but does not seem to be installed: - Run `Pkg.instantiate()` to install all recorded dependencies. """)) end + set_pkgorigin_version_path(pkg, path) # attempt to load the module file via the precompile cache locations if JLOptions().use_compiled_modules != 0 @@ -2143,7 +2149,6 @@ get_compiletime_preferences(::Nothing) = String[] @debug "Rejecting cache file $cachefile because dependency $req_key not found." return true # Won't be able to fulfill dependency end - set_pkgorigin_version_path(req_key, path) depmods[i] = (path, req_key, req_build_id) end end