-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add a suffix to a new cache files in case of failure of renaming it to an exisiting cache file already in use #48137
Conversation
…o an exisiting file
Why are we trying to overwrite the cache files? If they aren't different shouldn't they have different hashes? |
There is a maximum of 10 cache files for a package before we start overwriting old files. If you are continuously working on a package that means you would quickly start deleting cache files used by other projects. In the example above, I would have deleted the cache file for Example that I use in my global project. So that is why a cache file for a given project will overwrite an earlier cachefile from the same project. But there might be better strategies and heuristics. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but I would love to have the POSIX semantics that C++ now mandates in libuv ;)
base/loading.jl
Outdated
old_cachefiles = filter(x->startswith(x, basename(ocachename)) && endswith(x, ocacheext), readdir(cachepath)) | ||
nums = Set(1:length(old_cachefiles)) | ||
for file in old_cachefiles | ||
name = splitext(file)[1] | ||
s = split(name, '_') | ||
if length(s) == 3 # e.g. lLvWP_g5TNZ_3 | ||
i = tryparse(Int, last(s)) | ||
if i !== nothing | ||
delete!(nums, i) | ||
end | ||
end | ||
end | ||
# TODO: Risk for a race here if some other process grabs this name before us | ||
num = isempty(nums) ? 1 : minimum(nums) | ||
ocachefile = ocachename * "_$num" * ocacheext |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
old_cachefiles = filter(x->startswith(x, basename(ocachename)) && endswith(x, ocacheext), readdir(cachepath)) | |
nums = Set(1:length(old_cachefiles)) | |
for file in old_cachefiles | |
name = splitext(file)[1] | |
s = split(name, '_') | |
if length(s) == 3 # e.g. lLvWP_g5TNZ_3 | |
i = tryparse(Int, last(s)) | |
if i !== nothing | |
delete!(nums, i) | |
end | |
end | |
end | |
# TODO: Risk for a race here if some other process grabs this name before us | |
num = isempty(nums) ? 1 : minimum(nums) | |
ocachefile = ocachename * "_$num" * ocacheext | |
old_cachefiles = Set(readdir(cachepath)) | |
num = 1 | |
while true | |
ocachefile = ocachename * "_$num" * ocacheext | |
# ispath(ocachefile) || break | |
in(ocachefile, old_cachefiles) || break | |
end | |
# TODO: Risk for a race here if some other process grabs this name before us |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this part felt a bit convoluted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could also try to use tempname, since it implements mostly the same logic as this, but possibly does not support suffixes
Backport to 1.9? |
Note that Win32 and Linux have different semantics and API around atomic filesystem operations. Ideally you want to be using the ReplaceFile function on windows. |
You don't though, since that function is pretty weird and not like posix nor atomic. You want MoveFile, which is what this calls. |
In cases where we try to compile a cache file for a package that is already in use in another Julia session, Windows gives us an error because we are trying to rename a file to another file that is already in use (#48074).
This PR detects when the rename fails and adds a suffix
_i
to the cache file name wherei
is the smallest integer such that that file does not exist.Starting a few julia sessions and loading
Example
while editing it between every load gives a list of files like:Fixes #48074