Skip to content

Commit

Permalink
gracefully fall back to non pid locked precompilation if FileWatching…
Browse files Browse the repository at this point in the history
… is not loaded (#56570)

Fixes #56569
  • Loading branch information
KristofferC authored Nov 20, 2024
1 parent b660649 commit 4ed8814
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 16 deletions.
6 changes: 3 additions & 3 deletions base/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3839,9 +3839,9 @@ const compilecache_pidlock_stale_age = 10
function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=compilecache_pidlock_stale_age)
if @isdefined(mkpidlock_hook) && @isdefined(trymkpidlock_hook) && @isdefined(parse_pidfile_hook)
pidfile = compilecache_pidfile_path(pkg)
cachefile = invokelatest(trymkpidlock_hook, f, pidfile; stale_age)
cachefile = @invokelatest trymkpidlock_hook(f, pidfile; stale_age)
if cachefile === false
pid, hostname, age = invokelatest(parse_pidfile_hook, pidfile)
pid, hostname, age = @invokelatest parse_pidfile_hook(pidfile)
verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug
if isempty(hostname) || hostname == gethostname()
@logmsg verbosity "Waiting for another process (pid: $pid) to finish precompiling $(repr("text/plain", pkg)). Pidfile: $pidfile"
Expand All @@ -3850,7 +3850,7 @@ function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=compilec
end
# wait until the lock is available, but don't actually acquire it
# returning nothing indicates a process waited for another
return invokelatest(mkpidlock_hook, Returns(nothing), pidfile; stale_age)
return @invokelatest mkpidlock_hook(Returns(nothing), pidfile; stale_age)
end
return cachefile
else
Expand Down
29 changes: 16 additions & 13 deletions base/precompilation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module Precompilation

using Base: PkgId, UUID, SHA1, parsed_toml, project_file_name_uuid, project_names,
project_file_manifest_path, get_deps, preferences_names, isaccessibledir, isfile_casesensitive,
base_project
base_project, isdefined

# This is currently only used for pkgprecompile but the plan is to use this in code loading in the future
# see the `kc/codeloading2.0` branch
Expand Down Expand Up @@ -1031,14 +1031,16 @@ end

# Can be merged with `maybe_cachefile_lock` in loading?
function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLock, fancyprint::Bool, pkg_config, pkgspidlocked, hascolor)
if !(isdefined(Base, :mkpidlock_hook) && isdefined(Base, :trymkpidlock_hook) && Base.isdefined(Base, :parse_pidfile_hook))
return f()
end
pkg, config = pkg_config
flags, cacheflags = config
FileWatching = Base.loaded_modules[Base.PkgId(Base.UUID("7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"), "FileWatching")]
stale_age = Base.compilecache_pidlock_stale_age
pidfile = Base.compilecache_pidfile_path(pkg, flags=cacheflags)
cachefile = FileWatching.trymkpidlock(f, pidfile; stale_age)
cachefile = @invokelatest Base.trymkpidlock_hook(f, pidfile; stale_age)
if cachefile === false
pid, hostname, age = FileWatching.Pidfile.parse_pidfile(pidfile)
pid, hostname, age = @invokelatest Base.parse_pidfile_hook(pidfile)
pkgspidlocked[pkg_config] = if isempty(hostname) || hostname == gethostname()
if pid == getpid()
"an async task in this process (pidfile: $pidfile)"
Expand All @@ -1052,15 +1054,16 @@ function precompile_pkgs_maybe_cachefile_lock(f, io::IO, print_lock::ReentrantLo
println(io, " ", pkg.name, _color_string(" Being precompiled by $(pkgspidlocked[pkg_config])", Base.info_color(), hascolor))
end
# wait until the lock is available
FileWatching.mkpidlock(pidfile; stale_age) do
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded=true, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
return f() # precompile
end
end
@invokelatest Base.mkpidlock_hook(() -> begin
# double-check in case the other process crashed or the lock expired
if Base.isprecompiled(pkg; ignore_loaded=true, flags=cacheflags) # don't use caches for this as the env state will have changed
return nothing # returning nothing indicates a process waited for another
else
delete!(pkgspidlocked, pkg_config)
return f() # precompile
end
end,
pidfile; stale_age)
end
return cachefile
end
Expand Down

0 comments on commit 4ed8814

Please sign in to comment.