UserLock: Fix multi-threaded access to a global variable
This commit is contained in:
parent
a55f589720
commit
951357e5fb
1 changed files with 39 additions and 29 deletions
|
@ -434,7 +434,7 @@ private:
|
||||||
close that file again (without closing the original file
|
close that file again (without closing the original file
|
||||||
descriptor), we lose the lock. So we have to be *very* careful
|
descriptor), we lose the lock. So we have to be *very* careful
|
||||||
not to open a lock file on which we are holding a lock. */
|
not to open a lock file on which we are holding a lock. */
|
||||||
static PathSet lockedPaths; /* !!! not thread-safe */
|
static Sync<PathSet> lockedPaths_;
|
||||||
|
|
||||||
Path fnUserLock;
|
Path fnUserLock;
|
||||||
AutoCloseFD fdUserLock;
|
AutoCloseFD fdUserLock;
|
||||||
|
@ -460,7 +460,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PathSet UserLock::lockedPaths;
|
Sync<PathSet> UserLock::lockedPaths_;
|
||||||
|
|
||||||
|
|
||||||
UserLock::UserLock()
|
UserLock::UserLock()
|
||||||
|
@ -499,9 +499,15 @@ UserLock::UserLock()
|
||||||
|
|
||||||
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
||||||
|
|
||||||
if (lockedPaths.find(fnUserLock) != lockedPaths.end())
|
{
|
||||||
|
auto lockedPaths(lockedPaths_.lock());
|
||||||
|
if (lockedPaths->count(fnUserLock))
|
||||||
/* We already have a lock on this one. */
|
/* We already have a lock on this one. */
|
||||||
continue;
|
continue;
|
||||||
|
lockedPaths->insert(fnUserLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
|
||||||
if (!fd)
|
if (!fd)
|
||||||
|
@ -509,7 +515,6 @@ UserLock::UserLock()
|
||||||
|
|
||||||
if (lockFile(fd.get(), ltWrite, false)) {
|
if (lockFile(fd.get(), ltWrite, false)) {
|
||||||
fdUserLock = std::move(fd);
|
fdUserLock = std::move(fd);
|
||||||
lockedPaths.insert(fnUserLock);
|
|
||||||
user = i;
|
user = i;
|
||||||
uid = pw->pw_uid;
|
uid = pw->pw_uid;
|
||||||
|
|
||||||
|
@ -533,6 +538,10 @@ UserLock::UserLock()
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} catch (...) {
|
||||||
|
lockedPaths_.lock()->erase(fnUserLock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw Error(format("all build users are currently in use; "
|
throw Error(format("all build users are currently in use; "
|
||||||
|
@ -543,8 +552,9 @@ UserLock::UserLock()
|
||||||
|
|
||||||
UserLock::~UserLock()
|
UserLock::~UserLock()
|
||||||
{
|
{
|
||||||
assert(lockedPaths.count(fnUserLock));
|
auto lockedPaths(lockedPaths_.lock());
|
||||||
lockedPaths.erase(fnUserLock);
|
assert(lockedPaths->count(fnUserLock));
|
||||||
|
lockedPaths->erase(fnUserLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue