From 46d448a5102181ced2f598e350d29810de5a76fb Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 29 Jun 2022 03:29:33 -0400 Subject: [PATCH] loading: stop corrupting memory all over the place Regressions introduced by #45607 --- base/loading.jl | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index 0befe0fc0d0465..b3c0ee639a206e 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 @@ -1324,7 +1327,9 @@ function unreference_module(key::PkgId) end end -function set_pkgorigin_version_path(pkg, path) +# whoever takes the package_locks[pkg] must call this function immediately +function set_pkgorigin_version_path(pkg::PkgId, path::Union{String,Nothing}) + assert_havelock(require_lock) pkgorigin = get!(PkgOrigin, pkgorigins, pkg) if path !== nothing project_file = locate_project_file(joinpath(dirname(path), "..")) @@ -1337,6 +1342,7 @@ function set_pkgorigin_version_path(pkg, path) end end pkgorigin.path = path + nothing end # Returns `nothing` or the new(ish) module @@ -1356,13 +1362,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 @@ -1436,6 +1442,7 @@ end function _require_from_serialized(uuidkey::PkgId, path::String) @lock require_lock begin + set_pkgorigin_version_path(uuidkey, nothing) newm = _tryrequire_from_serialized(uuidkey, path) newm isa Module || throw(newm) # After successfully loading, notify downstream consumers @@ -2160,7 +2167,6 @@ end @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