Skip to content

Commit

Permalink
make extension not load twice on workers (#49441)
Browse files Browse the repository at this point in the history
(cherry picked from commit b1c0eac)
  • Loading branch information
KristofferC committed Apr 22, 2023
1 parent f6561ce commit 7c6dd4c
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 17 deletions.
5 changes: 5 additions & 0 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1189,9 +1189,12 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, <:An
end
end

loading_extension::Bool = false
function run_extension_callbacks(extid::ExtensionId)
assert_havelock(require_lock)
succeeded = try
# Used by Distributed to now load extensions in the package callback
global loading_extension = true
_require_prelocked(extid.id)
@debug "Extension $(extid.id.name) of $(extid.parentid.name) loaded"
true
Expand All @@ -1201,6 +1204,8 @@ function run_extension_callbacks(extid::ExtensionId)
@error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \
use `Base.retry_load_extensions()` to retry." exception=errs
false
finally
global loading_extension = false
end
return succeeded
end
Expand Down
3 changes: 3 additions & 0 deletions stdlib/Distributed/src/Distributed.jl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ function _require_callback(mod::Base.PkgId)
# broadcast top-level (e.g. from Main) import/using from node 1 (only)
@sync for p in procs()
p == 1 && continue
# Extensions are already loaded on workers by their triggers being loaded
# so no need to fire the callback upon extension being loaded on master.
Base.loading_extension && continue
@async_unwrap remotecall_wait(p) do
Base.require(mod)
nothing
Expand Down
47 changes: 30 additions & 17 deletions test/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1003,34 +1003,47 @@ end
try
proj = joinpath(@__DIR__, "project", "Extensions", "HasDepWithExtensions.jl")

function gen_extension_cmd(compile)
```$(Base.julia_cmd()) $compile --startup-file=no -e '
begin
push!(empty!(DEPOT_PATH), '$(repr(depot_path))')
using HasExtensions
Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension")
HasExtensions.ext_loaded && error("ext_loaded set")
using HasDepWithExtensions
Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set")
HasExtensions.ext_loaded || error("ext_loaded not set")
HasExtensions.ext_folder_loaded && error("ext_folder_loaded set")
HasDepWithExtensions.do_something() || error("do_something errored")
using ExtDep2
HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set")
end
'
```
function gen_extension_cmd(compile, distr=false)
load_distr = distr ? "using Distributed; addprocs(1)" : ""
ew = distr ? "@everywhere" : ""
cmd = """
$load_distr
begin
$ew push!(empty!(DEPOT_PATH), $(repr(depot_path)))
using HasExtensions
$ew using HasExtensions
$ew Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension")
$ew HasExtensions.ext_loaded && error("ext_loaded set")
using HasDepWithExtensions
$ew using HasDepWithExtensions
$ew Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set")
$ew HasExtensions.ext_loaded || error("ext_loaded not set")
$ew HasExtensions.ext_folder_loaded && error("ext_folder_loaded set")
$ew HasDepWithExtensions.do_something() || error("do_something errored")
using ExtDep2
$ew using ExtDep2
$ew HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set")
end
"""
return `$(Base.julia_cmd()) $compile --startup-file=no -e $cmd`
end

for compile in (`--compiled-modules=no`, ``, ``) # Once when requiring precompilation, once where it is already precompiled
cmd = gen_extension_cmd(compile)
cmd = addenv(cmd, "JULIA_LOAD_PATH" => proj)
cmd = pipeline(cmd; stdout, stderr)
@show compile
@test success(cmd)
end

sep = Sys.iswindows() ? ';' : ':'

cmd = gen_extension_cmd(``, true)
cmd = addenv(cmd, "JULIA_LOAD_PATH" => join([proj, "@stdlib"], sep))
str = read(cmd, String)
@test !occursin("Error during loading of extension", str)
@test !occursin("ConcurrencyViolationError", str)

# 48351
cmd = gen_extension_cmd(``)
cmd = addenv(cmd, "JULIA_LOAD_PATH" => join([mktempdir(), proj], sep))
Expand Down

0 comments on commit 7c6dd4c

Please sign in to comment.