Skip to content

Commit b1c0eac

Browse files
authored
make extension not load twice on workers (#49441)
1 parent 6b79e8c commit b1c0eac

File tree

3 files changed

+38
-17
lines changed

3 files changed

+38
-17
lines changed

base/loading.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,9 +1189,12 @@ function _insert_extension_triggers(parent::PkgId, extensions::Dict{String, <:An
11891189
end
11901190
end
11911191

1192+
loading_extension::Bool = false
11921193
function run_extension_callbacks(extid::ExtensionId)
11931194
assert_havelock(require_lock)
11941195
succeeded = try
1196+
# Used by Distributed to now load extensions in the package callback
1197+
global loading_extension = true
11951198
_require_prelocked(extid.id)
11961199
@debug "Extension $(extid.id.name) of $(extid.parentid.name) loaded"
11971200
true
@@ -1201,6 +1204,8 @@ function run_extension_callbacks(extid::ExtensionId)
12011204
@error "Error during loading of extension $(extid.id.name) of $(extid.parentid.name), \
12021205
use `Base.retry_load_extensions()` to retry." exception=errs
12031206
false
1207+
finally
1208+
global loading_extension = false
12041209
end
12051210
return succeeded
12061211
end

stdlib/Distributed/src/Distributed.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ function _require_callback(mod::Base.PkgId)
7676
# broadcast top-level (e.g. from Main) import/using from node 1 (only)
7777
@sync for p in procs()
7878
p == 1 && continue
79+
# Extensions are already loaded on workers by their triggers being loaded
80+
# so no need to fire the callback upon extension being loaded on master.
81+
Base.loading_extension && continue
7982
@async_unwrap remotecall_wait(p) do
8083
Base.require(mod)
8184
nothing

test/loading.jl

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,34 +1006,47 @@ end
10061006
try
10071007
proj = joinpath(@__DIR__, "project", "Extensions", "HasDepWithExtensions.jl")
10081008

1009-
function gen_extension_cmd(compile)
1010-
```$(Base.julia_cmd()) $compile --startup-file=no -e '
1011-
begin
1012-
push!(empty!(DEPOT_PATH), '$(repr(depot_path))')
1013-
using HasExtensions
1014-
Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension")
1015-
HasExtensions.ext_loaded && error("ext_loaded set")
1016-
using HasDepWithExtensions
1017-
Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set")
1018-
HasExtensions.ext_loaded || error("ext_loaded not set")
1019-
HasExtensions.ext_folder_loaded && error("ext_folder_loaded set")
1020-
HasDepWithExtensions.do_something() || error("do_something errored")
1021-
using ExtDep2
1022-
HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set")
1023-
end
1024-
'
1025-
```
1009+
function gen_extension_cmd(compile, distr=false)
1010+
load_distr = distr ? "using Distributed; addprocs(1)" : ""
1011+
ew = distr ? "@everywhere" : ""
1012+
cmd = """
1013+
$load_distr
1014+
begin
1015+
$ew push!(empty!(DEPOT_PATH), $(repr(depot_path)))
1016+
using HasExtensions
1017+
$ew using HasExtensions
1018+
$ew Base.get_extension(HasExtensions, :Extension) === nothing || error("unexpectedly got an extension")
1019+
$ew HasExtensions.ext_loaded && error("ext_loaded set")
1020+
using HasDepWithExtensions
1021+
$ew using HasDepWithExtensions
1022+
$ew Base.get_extension(HasExtensions, :Extension).extvar == 1 || error("extvar in Extension not set")
1023+
$ew HasExtensions.ext_loaded || error("ext_loaded not set")
1024+
$ew HasExtensions.ext_folder_loaded && error("ext_folder_loaded set")
1025+
$ew HasDepWithExtensions.do_something() || error("do_something errored")
1026+
using ExtDep2
1027+
$ew using ExtDep2
1028+
$ew HasExtensions.ext_folder_loaded || error("ext_folder_loaded not set")
1029+
end
1030+
"""
1031+
return `$(Base.julia_cmd()) $compile --startup-file=no -e $cmd`
10261032
end
10271033

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

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

1044+
cmd = gen_extension_cmd(``, true)
1045+
cmd = addenv(cmd, "JULIA_LOAD_PATH" => join([proj, "@stdlib"], sep))
1046+
str = read(cmd, String)
1047+
@test !occursin("Error during loading of extension", str)
1048+
@test !occursin("ConcurrencyViolationError", str)
1049+
10371050
# 48351
10381051
cmd = gen_extension_cmd(``)
10391052
cmd = addenv(cmd, "JULIA_LOAD_PATH" => join([mktempdir(), proj], sep))

0 commit comments

Comments
 (0)