Skip to content

Commit 8f44c47

Browse files
committed
Add hack to prevent precompilation deadlock on 1.10.
1 parent 942e431 commit 8f44c47

1 file changed

Lines changed: 51 additions & 1 deletion

File tree

src/oneAPI.jl

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,59 @@ include("sorting.jl")
7777
include("indexing.jl")
7878
export oneAPIBackend
7979

80+
# Work around a deadlock in Pkg's parallel precompilation on Julia 1.10, where it does
81+
# not pass `loadable_exts` to `Base.compilecache` (the kwarg is accidentally commented
82+
# out in Pkg's precompilation.jl), so a worker precompiling an extension freely loads
83+
# other extensions. If such an extension is being precompiled concurrently by another
84+
# worker, loading it blocks on a pidfile lock held by the Pkg driver, which in turn
85+
# waits for our worker: a deadlock. This bites oneAPI in particular, as it triggers
86+
# extensions of its own dependencies (AtomixoneAPIExt, AcceleratedKernelsoneAPIExt)
87+
# that have identical trigger sets and are thus precompiled concurrently.
88+
#
89+
# Mimic what Pkg on 1.11+ does by disallowing extension loading when precompiling an
90+
# extension. This needs to happen from `__init__`, which runs in the worker process
91+
# right before loading of oneAPI completes and extension callbacks are processed.
92+
function prevent_extension_deadlock()
93+
isdefined(Base, :loadable_extensions) || return
94+
isdefined(Base, :precompilation_target) || return
95+
Base.loadable_extensions === nothing || return # Pkg already restricted loading
96+
target = Base.precompilation_target
97+
(target === nothing || target.uuid === nothing) && return
98+
99+
# determine whether the precompilation target is an extension, i.e., whether its
100+
# entry-point lives in the `ext` directory of a parent package whose UUID also
101+
# generates the extension's UUID (the scheme used by `Base.insert_extension_triggers`)
102+
path = Base.locate_package(target)
103+
path === nothing && return
104+
dir = dirname(path)
105+
if basename(dir) != "ext"
106+
dir = dirname(dir)
107+
basename(dir) == "ext" || return
108+
end
109+
parent_uuid = nothing
110+
for proj in Base.project_names
111+
project_file = joinpath(dirname(dir), proj)
112+
if isfile(project_file)
113+
d = Base.parsed_toml(project_file)
114+
parent_uuid = get(d, "uuid", nothing)
115+
break
116+
end
117+
end
118+
parent_uuid isa String || return
119+
target.uuid == Base.uuid5(Base.UUID(parent_uuid), target.name) || return
120+
121+
Base.loadable_extensions = Base.PkgId[]
122+
return
123+
end
124+
80125
function __init__()
81126
precompiling = ccall(:jl_generating_output, Cint, ()) != 0
82-
precompiling && return
127+
if precompiling
128+
@static if VERSION < v"1.11"
129+
prevent_extension_deadlock()
130+
end
131+
return
132+
end
83133

84134
if oneL0.NEO_jll.is_available() && oneL0.functional[]
85135
if Sys.iswindows()

0 commit comments

Comments
 (0)