1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 01:51:47 +02:00

Make LocalStore thread-safe

Necessary for multi-threaded commands like "nix verify-paths".
This commit is contained in:
Eelco Dolstra 2016-04-08 18:07:13 +02:00
parent 05fbc606fc
commit f398949b40
5 changed files with 246 additions and 217 deletions

View file

@ -147,35 +147,36 @@ Path Store::addPermRoot(const Path & _storePath,
void LocalStore::addTempRoot(const Path & path)
{
auto state(_state.lock());
/* Create the temporary roots file for this process. */
if (fdTempRoots == -1) {
if (state->fdTempRoots == -1) {
while (1) {
Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str();
createDirs(dir);
fnTempRoots = (format("%1%/%2%")
% dir % getpid()).str();
state->fnTempRoots = (format("%1%/%2%") % dir % getpid()).str();
AutoCloseFD fdGCLock = openGCLock(ltRead);
if (pathExists(fnTempRoots))
if (pathExists(state->fnTempRoots))
/* It *must* be stale, since there can be no two
processes with the same pid. */
unlink(fnTempRoots.c_str());
unlink(state->fnTempRoots.c_str());
fdTempRoots = openLockFile(fnTempRoots, true);
state->fdTempRoots = openLockFile(state->fnTempRoots, true);
fdGCLock.close();
debug(format("acquiring read lock on %1%") % fnTempRoots);
lockFile(fdTempRoots, ltRead, true);
debug(format("acquiring read lock on %1%") % state->fnTempRoots);
lockFile(state->fdTempRoots, ltRead, true);
/* Check whether the garbage collector didn't get in our
way. */
struct stat st;
if (fstat(fdTempRoots, &st) == -1)
throw SysError(format("statting %1%") % fnTempRoots);
if (fstat(state->fdTempRoots, &st) == -1)
throw SysError(format("statting %1%") % state->fnTempRoots);
if (st.st_size == 0) break;
/* The garbage collector deleted this file before we could
@ -187,15 +188,15 @@ void LocalStore::addTempRoot(const Path & path)
/* Upgrade the lock to a write lock. This will cause us to block
if the garbage collector is holding our lock. */
debug(format("acquiring write lock on %1%") % fnTempRoots);
lockFile(fdTempRoots, ltWrite, true);
debug(format("acquiring write lock on %1%") % state->fnTempRoots);
lockFile(state->fdTempRoots, ltWrite, true);
string s = path + '\0';
writeFull(fdTempRoots, s);
writeFull(state->fdTempRoots, s);
/* Downgrade to a read lock. */
debug(format("downgrading to read lock on %1%") % fnTempRoots);
lockFile(fdTempRoots, ltRead, true);
debug(format("downgrading to read lock on %1%") % state->fnTempRoots);
lockFile(state->fdTempRoots, ltRead, true);
}