Skip to content

delay loading of extensions as much as possible #48674

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 16, 2023
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 46 additions & 40 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1080,7 +1080,6 @@ function register_restored_modules(sv::SimpleVector, pkg::PkgId, path::String)
end

function run_package_callbacks(modkey::PkgId)
run_extension_callbacks(modkey)
assert_havelock(require_lock)
unlock(require_lock)
try
Expand Down Expand Up @@ -1204,53 +1203,56 @@ function run_extension_callbacks(extid::ExtensionId)
return succeeded
end

function run_extension_callbacks(pkgid::PkgId)
function run_extension_callbacks()
assert_havelock(require_lock)
# take ownership of extids that depend on this pkgid
extids = pop!(EXT_DORMITORY, pkgid, nothing)
extids === nothing && return
for extid in extids
if extid.ntriggers > 0
# It is possible that pkgid was loaded in an environment
# below the one of the parent. This will cause a load failure when the
# pkg ext tries to load the triggers. Therefore, check this first
# before loading the pkg ext.
pkgenv = Base.identify_package_env(extid.id, pkgid.name)
ext_not_allowed_load = false
if pkgenv === nothing
ext_not_allowed_load = true
else
pkg, env = pkgenv
path = Base.locate_package(pkg, env)
if path === nothing
for pkgid in copy(keys(EXT_DORMITORY))
haskey(Base.loaded_modules, pkgid) || continue
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this be any better?

Suggested change
for pkgid in copy(keys(EXT_DORMITORY))
haskey(Base.loaded_modules, pkgid) || continue
for pkgid in intersect(keys(Base.loaded_modules), keys(Base.EXT_DORMITORY))

I also wonder if there is any meaningful way to sort this list to be predictable (if that is worthwhile to do), for example we could try to sort the result, but isless(::Base.PkgId, ::Base.PkgId) is not defined.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this and also sorted by UUID.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hope folks don't decide to give their packages low or high uuids to hack trigger order.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't really matter, this is just to keep it consistent.

# take ownership of extids that depend on this pkgid
extids = pop!(EXT_DORMITORY, pkgid, nothing)
extids === nothing && continue
for extid in extids
if extid.ntriggers > 0
# It is possible that pkgid was loaded in an environment
# below the one of the parent. This will cause a load failure when the
# pkg ext tries to load the triggers. Therefore, check this first
# before loading the pkg ext.
pkgenv = Base.identify_package_env(extid.id, pkgid.name)
ext_not_allowed_load = false
if pkgenv === nothing
ext_not_allowed_load = true
else
pkg, env = pkgenv
path = Base.locate_package(pkg, env)
if path === nothing
ext_not_allowed_load = true
end
end
if ext_not_allowed_load
@debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \
since $(pkgid.name) loaded in environment lower in load path"
# indicate extid is expected to fail
extid.ntriggers *= -1
else
# indicate pkgid is loaded
extid.ntriggers -= 1
end
end
if ext_not_allowed_load
@debug "Extension $(extid.id.name) of $(extid.parentid.name) will not be loaded \
since $(pkgid.name) loaded in environment lower in load path"
# indicate extid is expected to fail
extid.ntriggers *= -1
else
if extid.ntriggers < 0
# indicate pkgid is loaded
extid.ntriggers -= 1
extid.ntriggers += 1
succeeded = false
else
succeeded = true
end
if extid.ntriggers == 0
# actually load extid, now that all dependencies are met,
# and record the result
succeeded = succeeded && run_extension_callbacks(extid)
succeeded || push!(EXT_DORMITORY_FAILED, extid)
end
end
if extid.ntriggers < 0
# indicate pkgid is loaded
extid.ntriggers += 1
succeeded = false
else
succeeded = true
end
if extid.ntriggers == 0
# actually load extid, now that all dependencies are met,
# and record the result
succeeded = succeeded && run_extension_callbacks(extid)
succeeded || push!(EXT_DORMITORY_FAILED, extid)
end
end
nothing
return
end

"""
Expand Down Expand Up @@ -1665,6 +1667,10 @@ function _require_prelocked(uuidkey::PkgId, env=nothing)
else
newm = root_module(uuidkey)
end
# Load extensions when not precompiling and not in a nested package load
if JLOptions().incremental == 0 && isempty(package_locks)
run_extension_callbacks()
end
return newm
end

Expand Down