libstore: bind FdLock to AutoCloseFD and make resource-safe

Change-Id: I2451c15bd0e7d3a5a537bbb65502fd4a18ae0c22
This commit is contained in:
eldritch horrors
2025-02-08 08:33:26 +00:00
parent 00a1afe022
commit 8f5f33c9d8
4 changed files with 33 additions and 26 deletions
+3 -3
View File
@@ -129,9 +129,9 @@ void LocalStore::addTempRoot(const StorePath & path)
/* Try to acquire a shared global GC lock (non-blocking). This
only succeeds if the garbage collector is not currently
running. */
FdLock gcLock(_fdGCLock.lock()->get(), ltRead);
FdLock gcLock(*_fdGCLock.lock(), ltRead, FdLock::dont_wait);
if (!gcLock.acquired) {
if (!gcLock.valid()) {
/* We couldn't get a shared global GC lock, so the garbage
collector is running. So we have to connect to the garbage
collector and inform it about our root. */
@@ -583,7 +583,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
here because then in auto-gc mode, another thread could
downgrade our exclusive lock. */
auto fdGCLock = openGCLock();
FdLock gcLock(fdGCLock.get(), ltWrite, "waiting for the big garbage collector lock...");
FdLock gcLock(fdGCLock, ltWrite, "waiting for the big garbage collector lock...");
/* Synchronisation point to test ENOENT handling in
addTempRoot(), see tests/gc-non-blocking.sh. */
+1 -1
View File
@@ -1527,7 +1527,7 @@ try {
/* Acquire the global GC lock to get a consistent snapshot of
existing and valid paths. */
auto fdGCLock = openGCLock();
FdLock gcLock(fdGCLock.get(), ltRead, "waiting for the big garbage collector lock...");
FdLock gcLock(fdGCLock, ltRead, "waiting for the big garbage collector lock...");
StorePathSet validPaths;
+9 -8
View File
@@ -1,4 +1,5 @@
#include "lix/libstore/pathlocks.hh"
#include "lix/libutil/file-descriptor.hh"
#include "lix/libutil/logging.hh"
#include "lix/libutil/signals.hh"
@@ -208,19 +209,19 @@ void PathLocks::setDeletion(bool deletePaths)
}
FdLock::FdLock(int fd, LockType lockType)
: fd(fd)
FdLock::FdLock(AutoCloseFD & fd, LockType lockType, DontWait)
{
acquired = tryLockFile(fd, lockType);
if (tryLockFile(fd.get(), lockType)) {
this->fd.reset(&fd);
}
}
FdLock::FdLock(int fd, LockType lockType, std::string_view waitMsg)
: fd(fd)
FdLock::FdLock(AutoCloseFD & fd, LockType lockType, std::string_view waitMsg)
{
if (!tryLockFile(fd, lockType)) {
if (!tryLockFile(fd.get(), lockType)) {
printInfo("%s", waitMsg);
lockFile(fd, lockType);
acquired = true;
lockFile(fd.get(), lockType);
this->fd.reset(&fd);
}
}
+20 -14
View File
@@ -57,23 +57,29 @@ public:
void setDeletion(bool deletePaths);
};
struct FdLock
class FdLock
{
int fd;
bool acquired = false;
FdLock(int fd, LockType lockType);
FdLock(int fd, LockType lockType, std::string_view waitMsg);
~FdLock()
struct Unlocker
{
try {
if (acquired)
unlockFile(fd);
} catch (SysError &) {
ignoreExceptionInDestructor();
void operator()(AutoCloseFD * fd)
{
try {
unlockFile(fd->get());
} catch (SysError &) {
ignoreExceptionInDestructor();
}
}
}
};
std::unique_ptr<AutoCloseFD, Unlocker> fd;
public:
static constexpr struct DontWait { explicit DontWait() = default; } dont_wait;
FdLock(AutoCloseFD & fd, LockType lockType, DontWait);
FdLock(AutoCloseFD & fd, LockType lockType, std::string_view waitMsg);
bool valid() const { return bool(fd); }
};
}