aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc70
1 files changed, 38 insertions, 32 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 26e2b0dca..366dbfb0a 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -29,7 +29,7 @@ static string gcRootsDir = "gcroots";
read. To be precise: when they try to create a new temporary root
file, they will block until the garbage collector has finished /
yielded the GC lock. */
-int LocalStore::openGCLock(LockType lockType)
+AutoCloseFD LocalStore::openGCLock(LockType lockType)
{
Path fnGCLock = (format("%1%/%2%")
% stateDir % gcLockName).str();
@@ -49,7 +49,7 @@ int LocalStore::openGCLock(LockType lockType)
process that can open the file for reading can DoS the
collector. */
- return fdGCLock.release();
+ return fdGCLock;
}
@@ -221,26 +221,22 @@ void LocalStore::findTempRoots(FDs & fds, Roots & tempRoots, bool censor)
//FDPtr fd(new AutoCloseFD(openLockFile(path, false)));
//if (*fd == -1) continue;
- if (path != fnTempRoots) {
-
- /* Try to acquire a write lock without blocking. This can
- only succeed if the owning process has died. In that case
- we don't care about its temporary roots. */
- if (lockFile(fd->get(), ltWrite, false)) {
- printError(format("removing stale temporary roots file '%1%'") % path);
- unlink(path.c_str());
- writeFull(fd->get(), "d");
- continue;
- }
-
- /* Acquire a read lock. This will prevent the owning process
- from upgrading to a write lock, therefore it will block in
- addTempRoot(). */
- debug(format("waiting for read lock on '%1%'") % path);
- lockFile(fd->get(), ltRead, true);
-
+ /* Try to acquire a write lock without blocking. This can
+ only succeed if the owning process has died. In that case
+ we don't care about its temporary roots. */
+ if (lockFile(fd->get(), ltWrite, false)) {
+ printError(format("removing stale temporary roots file '%1%'") % path);
+ unlink(path.c_str());
+ writeFull(fd->get(), "d");
+ continue;
}
+ /* Acquire a read lock. This will prevent the owning process
+ from upgrading to a write lock, therefore it will block in
+ addTempRoot(). */
+ debug(format("waiting for read lock on '%1%'") % path);
+ lockFile(fd->get(), ltRead, true);
+
/* Read the entire file. */
string contents = readFile(fd->get());
@@ -444,17 +440,22 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
}
#if !defined(__linux__)
- try {
- std::regex lsofRegex(R"(^n(/.*)$)");
- auto lsofLines =
- tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
- for (const auto & line : lsofLines) {
- std::smatch match;
- if (std::regex_match(line, match, lsofRegex))
- unchecked[match[1]].emplace("{lsof}");
+ // lsof is really slow on OS X. This actually causes the gc-concurrent.sh test to fail.
+ // See: https://github.com/NixOS/nix/issues/3011
+ // Because of this we disable lsof when running the tests.
+ if (getEnv("_NIX_TEST_NO_LSOF") == "") {
+ try {
+ std::regex lsofRegex(R"(^n(/.*)$)");
+ auto lsofLines =
+ tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
+ for (const auto & line : lsofLines) {
+ std::smatch match;
+ if (std::regex_match(line, match, lsofRegex))
+ unchecked[match[1]].emplace("{lsof}");
+ }
+ } catch (ExecError & e) {
+ /* lsof not installed, lsof failed */
}
- } catch (ExecError & e) {
- /* lsof not installed, lsof failed */
}
#endif
@@ -866,7 +867,12 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
void LocalStore::autoGC(bool sync)
{
- auto getAvail = [this]() {
+ static auto fakeFreeSpaceFile = getEnv("_NIX_TEST_FREE_SPACE_FILE", "");
+
+ auto getAvail = [this]() -> uint64_t {
+ if (!fakeFreeSpaceFile.empty())
+ return std::stoll(readFile(fakeFreeSpaceFile));
+
struct statvfs st;
if (statvfs(realStoreDir.c_str(), &st))
throw SysError("getting filesystem info about '%s'", realStoreDir);
@@ -887,7 +893,7 @@ void LocalStore::autoGC(bool sync)
auto now = std::chrono::steady_clock::now();
- if (now < state->lastGCCheck + std::chrono::seconds(5)) return;
+ if (now < state->lastGCCheck + std::chrono::seconds(settings.minFreeCheckInterval)) return;
auto avail = getAvail();