Skip to content

Commit

Permalink
Rewrite force_symlink to avoid a race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed Oct 16, 2022
1 parent 8e3eaf7 commit 990be4c
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/setup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,21 @@ gaproot() = @get_scratch!(scratch_key)
#
#############################################################################

function force_symlink(p::AbstractString, np::AbstractString)
rm(np; force = true)
symlink(p, np)
# ensure `source` is a symlink pointing to `target` in a way that is hopefully
# safe against races with other Julia processes doing the exact same thing
function force_symlink(source::AbstractString, target::AbstractString)
# We previously used `rm` followed by `symlink`, but this can cause a
# race if multiple processes invoke `rm` concurrently (which works if
# one uses `force=true`), and then try to invoke `symlink`
# concurrently (which then fails in all but one process).
#
# So instead we create the symlink with a temporary name, and then use
# an atomic `rename` to rename it to the `target` name. The latter
# unfortunately requires invoking an undocumented function.
tmpfile = tempname(dirname(abspath(target)); cleanup=false)
symlink(source, tmpfile)
Base.Filesystem.rename(tmpfile, target)
return nothing
end

function read_sysinfo_gap(dir::String)
Expand Down

0 comments on commit 990be4c

Please sign in to comment.