@@ -927,6 +927,8 @@ function find_all_in_cache_path(pkg::PkgId)
927
927
end
928
928
929
929
ocachefile_from_cachefile (cachefile) = string (chopsuffix (cachefile, " .ji" ), " ." , Base. Libc. dlext)
930
+ cachefile_from_ocachefile (cachefile) = string (chopsuffix (cachefile, " .$(Base. Libc. dlext) " ), " .ji" )
931
+
930
932
931
933
# use an Int counter so that nested @time_imports calls all remain open
932
934
const TIMING_IMPORTS = Threads. Atomic {Int} (0 )
@@ -2091,7 +2093,6 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
2091
2093
if pkg. uuid != = nothing
2092
2094
entrypath, entryfile = cache_file_entry (pkg)
2093
2095
cachefiles = filter! (x -> startswith (x, entryfile * " _" ) && endswith (x, " .ji" ), readdir (cachepath))
2094
-
2095
2096
if length (cachefiles) >= MAX_NUM_PRECOMPILE_FILES[]
2096
2097
idx = findmin (mtime .(joinpath .(cachepath, cachefiles)))[2 ]
2097
2098
evicted_cachefile = joinpath (cachepath, cachefiles[idx])
@@ -2104,11 +2105,31 @@ function compilecache(pkg::PkgId, path::String, internal_stderr::IO = stderr, in
2104
2105
end
2105
2106
end
2106
2107
2107
- # this is atomic according to POSIX (not Win32):
2108
- rename (tmppath, cachefile; force= true )
2109
2108
if cache_objects
2110
- rename (tmppath_so, ocachefile:: String ; force= true )
2109
+ try
2110
+ rename (tmppath_so, ocachefile:: String ; force= true )
2111
+ catch e
2112
+ e isa IOError || rethrow ()
2113
+ isfile (ocachefile) || rethrow ()
2114
+ # Windows prevents renaming a file that is in use so if there is a Julia session started
2115
+ # with a package image loaded, we cannot rename that file.
2116
+ # The code belows append a `_i` to the name of the cache file where `i` is the smallest number such that
2117
+ # that cache file does not exist.
2118
+ ocachename, ocacheext = splitext (ocachefile)
2119
+ old_cachefiles = Set (readdir (cachepath))
2120
+ num = 1
2121
+ while true
2122
+ ocachefile = ocachename * " _$num " * ocacheext
2123
+ in (basename (ocachefile), old_cachefiles) || break
2124
+ num += 1
2125
+ end
2126
+ # TODO : Risk for a race here if some other process grabs this name before us
2127
+ cachefile = cachefile_from_ocachefile (ocachefile)
2128
+ rename (tmppath_so, ocachefile:: String ; force= true )
2129
+ end
2111
2130
end
2131
+ # this is atomic according to POSIX (not Win32):
2132
+ rename (tmppath, cachefile; force= true )
2112
2133
return cachefile, ocachefile
2113
2134
end
2114
2135
finally
0 commit comments