Skip to content

Commit

Permalink
loading: precompile files might try _require the same package twice
Browse files Browse the repository at this point in the history
fix #25604
  • Loading branch information
vtjnash committed Jan 17, 2018
1 parent 26a2ea2 commit 9e35dcf
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 42 deletions.
84 changes: 42 additions & 42 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,31 @@ function _include_from_serialized(path::String, depmods::Vector{Any})
return restored
end

function _tryrequire_from_serialized(modname::Symbol, uuid::UInt64, modpath::Union{Nothing, String})
if root_module_exists(modname)
M = root_module(modname)
if module_name(M) === modname && module_uuid(M) === uuid
return M
end
else
if modpath === nothing
modpath = find_package(string(modname))
modpath === nothing && return ErrorException("Required dependency $modname not found in current path.")
end
mod = _require_search_from_serialized(modname, String(modpath))
if !isa(mod, Bool)
for callback in package_callbacks
invokelatest(callback, modname)
end
for M in mod::Vector{Any}
if module_name(M) === modname && module_uuid(M) === uuid
return M
end
end
end
end
return nothing
end

function _require_from_serialized(path::String)
# loads a precompile cache file, ignoring stale_cachfile tests
Expand All @@ -151,28 +176,9 @@ function _require_from_serialized(path::String)
depmods = Vector{Any}(uninitialized, ndeps)
for i in 1:ndeps
modname, uuid = depmodnames[i]
if root_module_exists(modname)
M = root_module(modname)
if module_name(M) === modname && module_uuid(M) === uuid
depmods[i] = M
end
else
modpath = find_package(string(modname))
modpath === nothing && return ErrorException("Required dependency $modname not found in current path.")
mod = _require_search_from_serialized(modname, String(modpath))
if !isa(mod, Bool)
for M in mod::Vector{Any}
if module_name(M) === modname && module_uuid(M) === uuid
depmods[i] = M
break
end
end
for callback in package_callbacks
invokelatest(callback, modname)
end
end
end
isassigned(depmods, i) || return ErrorException("Required dependency $modname failed to load from a cache file.")
dep = _tryrequire_from_serialized(modname, uuid, nothing)
dep === nothing && return ErrorException("Required dependency $modname failed to load from a cache file.")
depmods[i] = dep::Module
end
# then load the file
return _include_from_serialized(path, depmods)
Expand All @@ -184,33 +190,27 @@ end
function _require_search_from_serialized(mod::Symbol, sourcepath::String)
paths = find_all_in_cache_path(String(mod)) # cache files for sourcepath are stored keyed by the `mod` symbol name
for path_to_try in paths::Vector{String}
deps = stale_cachefile(sourcepath, path_to_try)
if deps === true
staledeps = stale_cachefile(sourcepath, path_to_try)
if staledeps === true
continue
end
# finish loading module graph into deps
for i in 1:length(deps)
dep = deps[i]
# finish loading module graph into staledeps
for i in 1:length(staledeps)
dep = staledeps[i]
dep isa Module && continue
modpath, modname, uuid = dep::Tuple{String, Symbol, UInt64}
reqmod = _require_search_from_serialized(modname, modpath)
if !isa(reqmod, Bool)
for M in reqmod::Vector{Any}
if module_name(M) === modname && module_uuid(M) === uuid
deps[i] = M
break
end
end
for callback in package_callbacks
invokelatest(callback, modname)
end
end
if !isa(deps[i], Module)
dep = _tryrequire_from_serialized(modname, uuid, modpath)
if dep === nothing
@debug "Required dependency $modname failed to load from cache file for $modpath."
continue
staledeps = true
break
end
staledeps[i] = dep::Module
end
if staledeps === true
continue
end
restored = _include_from_serialized(path_to_try, deps)
restored = _include_from_serialized(path_to_try, staledeps)
if isa(restored, Exception)
@debug "Deserialization checks failed while attempting to load cache from $path_to_try" exception=restored
else
Expand Down
37 changes: 37 additions & 0 deletions test/compile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -674,4 +674,41 @@ let
end
end

let
load_path = mktempdir()
load_cache_path = mktempdir()
try
write(joinpath(load_path, "A25604.jl"),
"""
__precompile__(true)
module A25604
using B25604
using C25604
end
""")
write(joinpath(load_path, "B25604.jl"),
"""
__precompile__()
module B25604
end
""")
write(joinpath(load_path, "C25604.jl"),
"""
__precompile__()
module C25604
using B25604
end
""")

pushfirst!(LOAD_PATH, load_path)
pushfirst!(Base.LOAD_CACHE_PATH, load_cache_path)

Base.compilecache(:A25604)
@test_nowarn @eval using A25604
finally
rm(load_path, recursive=true)
rm(load_cache_path, recursive=true)
end
end

end # !withenv

0 comments on commit 9e35dcf

Please sign in to comment.