mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
local-binary-cache-store: Add retry loop to upsertFile
Handle race conditions in binary cache file creation by retrying with a new temporary name on EEXIST errors. Uses existing makeTempPath which already has an atomic counter.
This commit is contained in:
parent
bc73faf88f
commit
f124293024
1 changed files with 26 additions and 7 deletions
|
@ -58,13 +58,32 @@ protected:
|
|||
const std::string & mimeType) override
|
||||
{
|
||||
auto path2 = config->binaryCacheDir + "/" + path;
|
||||
static std::atomic<int> counter{0};
|
||||
Path tmp = fmt("%s.tmp.%d.%d", path2, getpid(), ++counter);
|
||||
AutoDelete del(tmp, false);
|
||||
StreamToSourceAdapter source(istream);
|
||||
writeFile(tmp, source);
|
||||
std::filesystem::rename(tmp, path2);
|
||||
del.cancel();
|
||||
|
||||
/* Retry loop for handling race conditions */
|
||||
while (true) {
|
||||
Path tmp = makeTempPath(dirOf(path2), baseNameOf(path2) + ".tmp");
|
||||
AutoDelete del(tmp, false);
|
||||
|
||||
StreamToSourceAdapter source(istream);
|
||||
try {
|
||||
writeFile(tmp, source);
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "while writing to temporary file '%s' for '%s'", tmp, path2);
|
||||
}
|
||||
|
||||
try {
|
||||
std::filesystem::rename(tmp, path2);
|
||||
del.cancel();
|
||||
break; /* Success! */
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
if (e.code() == std::errc::file_exists) {
|
||||
/* Race condition: another process created the same file.
|
||||
Try again with a different name. */
|
||||
continue;
|
||||
}
|
||||
throw SysError("renaming '%s' to '%s'", tmp, path2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void getFile(const std::string & path, Sink & sink) override
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue