mirror of
https://github.com/NixOS/nix
synced 2025-06-24 22:11:15 +02:00
local-store: Fix potential race in build log creation
Add atomic counter to temporary log file names and retry loop to handle EEXIST errors. If another process creates the log file first, we gracefully exit since the log already exists.
This commit is contained in:
parent
975b2c2edd
commit
bc73faf88f
1 changed files with 28 additions and 3 deletions
|
@ -24,6 +24,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <sys/types.h>
|
||||
|
@ -1666,11 +1667,35 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log)
|
|||
|
||||
createDirs(dirOf(logPath));
|
||||
|
||||
auto tmpFile = fmt("%s.tmp.%d", logPath, getpid());
|
||||
/* Retry loop for temporary log file creation to handle race conditions */
|
||||
while (true) {
|
||||
auto tmpFile = makeTempPath(dirOf(logPath), baseNameOf(logPath) + ".tmp");
|
||||
|
||||
writeFile(tmpFile, compress("bzip2", log));
|
||||
try {
|
||||
writeFile(tmpFile, compress("bzip2", log));
|
||||
} catch (Error & e) {
|
||||
e.addTrace({}, "writing build log to '%s'", tmpFile);
|
||||
throw;
|
||||
}
|
||||
|
||||
std::filesystem::rename(tmpFile, logPath);
|
||||
try {
|
||||
std::filesystem::rename(tmpFile, logPath);
|
||||
break; /* Success! */
|
||||
} catch (std::filesystem::filesystem_error & e) {
|
||||
try {
|
||||
std::filesystem::remove(tmpFile);
|
||||
} catch (...) {
|
||||
/* Ignore errors removing the temp file */
|
||||
}
|
||||
|
||||
if (e.code() == std::errc::file_exists) {
|
||||
/* Another process created the log file. That's fine, we're done. */
|
||||
break;
|
||||
}
|
||||
|
||||
throw SysError("renaming temporary file '%1%' to '%2%'", tmpFile, logPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> LocalStore::getVersion()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue