@@ -77,9 +77,59 @@ include("sorting.jl")
7777include (" indexing.jl" )
7878export 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+
80125function __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