diff --git a/base/loading.jl b/base/loading.jl index f5c7aa28395ef..b9742ec045b19 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -2819,11 +2819,20 @@ global mkpidlock_hook global trymkpidlock_hook global parse_pidfile_hook -# allows processes to wait if another process is precompiling a given source already -function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String) +# The preferences hash is only known after precompilation so just assume no preferences +# meaning that if all other conditions are equal, the same package cannot be precompiled +# with different preferences at the same time. +compilecache_pidfile_path(pkg::PkgId) = compilecache_path(pkg, UInt64(0)) * ".pidfile" + +# Allows processes to wait if another process is precompiling a given source already. +# The lock file is deleted and precompilation will proceed after `stale_age` seconds if +# - the locking process no longer exists +# - the lock is held by another host, since processes cannot be checked remotely +# or after `stale_age * 25` seconds if it does still exist. +function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String; stale_age=60) if @isdefined(mkpidlock_hook) && @isdefined(trymkpidlock_hook) && @isdefined(parse_pidfile_hook) - pidfile = string(srcpath, ".pidlock") - cachefile = invokelatest(trymkpidlock_hook, f, pidfile) + pidfile = compilecache_pidfile_path(pkg) + cachefile = invokelatest(trymkpidlock_hook, f, pidfile; stale_age) if cachefile === false pid, hostname, age = invokelatest(parse_pidfile_hook, pidfile) verbosity = isinteractive() ? CoreLogging.Info : CoreLogging.Debug @@ -2834,7 +2843,7 @@ function maybe_cachefile_lock(f, pkg::PkgId, srcpath::String) 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) + return invokelatest(mkpidlock_hook, Returns(nothing), pidfile; stale_age) end return cachefile else