Skip to content

Commit a7e9bcc

Browse files
nhz2IanButterworth
authored andcommitted
retry rename (#4001)
(cherry picked from commit bc51db7)
1 parent cab7300 commit a7e9bcc

File tree

1 file changed

+28
-6
lines changed

1 file changed

+28
-6
lines changed

src/Artifacts.jl

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,42 @@ Either rename the directory at `temp_dir` to `new_path` and set it to read-only
6565
or if `new_path` artifact already exists try to do nothing.
6666
"""
6767
function _mv_temp_artifact_dir(temp_dir::String, new_path::String)::Nothing
68-
if !isdir(new_path)
68+
# Sometimes a rename can fail because the temp_dir is locked by
69+
# anti-virus software scanning the new files.
70+
# In this case we want to sleep and try again.
71+
# I am using the list of error codes to retry from:
72+
# https://github.com/isaacs/node-graceful-fs/blob/234379906b7d2f4c9cfeb412d2516f42b0fb4953/polyfills.js#L87
73+
# Retry for up to about 60 seconds by retrying 20 times with exponential backoff.
74+
retry = 0
75+
max_num_retries = 20 # maybe this should be configurable?
76+
sleep_amount = 0.01 # seconds
77+
max_sleep_amount = 5.0 # seconds
78+
while true
79+
isdir(new_path) && return
6980
# This next step is like
7081
# `mv(temp_dir, new_path)`.
7182
# However, `mv` defaults to `cp` if `rename` returns an error.
7283
# `cp` is not atomic, so avoid the potential of calling it.
7384
err = ccall(:jl_fs_rename, Int32, (Cstring, Cstring), temp_dir, new_path)
74-
# Ignore rename error, but ensure `new_path` exists.
75-
if !isdir(new_path)
76-
error("$(repr(new_path)) could not be made")
85+
if err 0
86+
# rename worked
87+
chmod(new_path, filemode(dirname(new_path)))
88+
set_readonly(new_path)
89+
return
90+
else
91+
# Ignore rename error if `new_path` exists.
92+
isdir(new_path) && return
93+
if retry < max_num_retries && err (Base.UV_EACCES, Base.UV_EPERM, Base.UV_EBUSY)
94+
sleep(sleep_amount)
95+
sleep_amount = min(sleep_amount*2.0, max_sleep_amount)
96+
retry += 1
97+
else
98+
Base.uv_error("rename of $(repr(temp_dir)) to $(repr(new_path))", err)
99+
end
77100
end
78101
chmod(new_path, filemode(dirname(new_path)))
79102
set_readonly(new_path)
80103
end
81-
nothing
82104
end
83105

84106
"""
@@ -485,7 +507,7 @@ function with_show_download_info(f, io, name, quiet_download)
485507
if !quiet_download
486508
fancyprint && print(io, "\033[1A") # move cursor up one line
487509
fancyprint && print(io, "\033[2K") # clear line
488-
if success
510+
if success
489511
fancyprint && printpkgstyle(io, :Downloaded, "artifact: $name")
490512
else
491513
printpkgstyle(io, :Failure, "artifact: $name", color = :red)

0 commit comments

Comments
 (0)