aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
authorGuillaume Maudoux <layus.on@gmail.com>2019-02-27 23:32:12 +0100
committerGuillaume Maudoux <layus.on@gmail.com>2019-03-10 00:56:09 +0100
commit43331d634498154f6a1835c8c417dd07eaefd45d (patch)
treed1f60ee96248c02024cabc86809fd54f7e3b4bc5 /src/libstore/gc.cc
parent5886bc5996537fbf00d1fcfbb29595b8ccc9743e (diff)
detail memory roots
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc61
1 files changed, 31 insertions, 30 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index b415d5421..ecfa5e1ed 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -333,9 +333,7 @@ Roots LocalStore::findRootsNoTemp()
NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them
from being garbage collected). */
- size_t n = 0;
- for (auto & root : findRuntimeRoots())
- roots[fmt("{memory:%d}", n++)] = root;
+ findRuntimeRoots(roots);
return roots;
}
@@ -357,8 +355,7 @@ Roots LocalStore::findRoots()
return roots;
}
-
-static void readProcLink(const string & file, StringSet & paths)
+static void readProcLink(const string & file, Roots & roots)
{
/* 64 is the starting buffer size gnu readlink uses... */
auto bufsiz = ssize_t{64};
@@ -377,7 +374,7 @@ try_again:
goto try_again;
}
if (res > 0 && buf[0] == '/')
- paths.emplace(static_cast<char *>(buf), res);
+ roots.emplace(file, std::string(static_cast<char *>(buf), res));
return;
}
@@ -387,20 +384,20 @@ static string quoteRegexChars(const string & raw)
return std::regex_replace(raw, specialRegex, R"(\$&)");
}
-static void readFileRoots(const char * path, StringSet & paths)
+static void readFileRoots(const char * path, Roots & roots)
{
try {
- paths.emplace(readFile(path));
+ roots.emplace(path, readFile(path));
} catch (SysError & e) {
if (e.errNo != ENOENT && e.errNo != EACCES)
throw;
}
}
-PathSet LocalStore::findRuntimeRoots()
+void LocalStore::findRuntimeRoots(Roots & roots)
{
- PathSet roots;
- StringSet paths;
+ Roots unchecked;
+
auto procDir = AutoCloseDir{opendir("/proc")};
if (procDir) {
struct dirent * ent;
@@ -410,8 +407,8 @@ PathSet LocalStore::findRuntimeRoots()
while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) {
- readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), paths);
- readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), paths);
+ readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), unchecked);
+ readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), unchecked);
auto fdStr = (format("/proc/%1%/fd") % ent->d_name).str();
auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
@@ -423,7 +420,7 @@ PathSet LocalStore::findRuntimeRoots()
struct dirent * fd_ent;
while (errno = 0, fd_ent = readdir(fdDir.get())) {
if (fd_ent->d_name[0] != '.') {
- readProcLink((format("%1%/%2%") % fdStr % fd_ent->d_name).str(), paths);
+ readProcLink((format("%1%/%2%") % fdStr % fd_ent->d_name).str(), unchecked);
}
}
if (errno) {
@@ -434,18 +431,22 @@ PathSet LocalStore::findRuntimeRoots()
fdDir.reset();
try {
- auto mapLines =
- tokenizeString<std::vector<string>>(readFile((format("/proc/%1%/maps") % ent->d_name).str(), true), "\n");
+ auto mapFile = (format("/proc/%1%/maps") % ent->d_name).str();
+ auto mapLines = tokenizeString<std::vector<string>>(readFile(mapFile, true), "\n");
+ int n = 0;
for (const auto& line : mapLines) {
+ n++;
auto match = std::smatch{};
if (std::regex_match(line, match, mapRegex))
- paths.emplace(match[1]);
+ unchecked.emplace((format("{%1%:%2%}") % mapFile % n).str(), match[1]);
}
- auto envString = readFile((format("/proc/%1%/environ") % ent->d_name).str(), true);
+ auto envFile = (format("/proc/%1%/environ") % ent->d_name).str();
+ auto envString = readFile(envFile, true);
auto env_end = std::sregex_iterator{};
+ n = 0;
for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i)
- paths.emplace(i->str());
+ unchecked.emplace((format("{%1%:%2%}") % envFile % envString).str(), i->str());
} catch (SysError & e) {
if (errno == ENOENT || errno == EACCES || errno == ESRCH)
continue;
@@ -462,10 +463,11 @@ PathSet LocalStore::findRuntimeRoots()
std::regex lsofRegex(R"(^n(/.*)$)");
auto lsofLines =
tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
+ int n = 0;
for (const auto & line : lsofLines) {
std::smatch match;
if (std::regex_match(line, match, lsofRegex))
- paths.emplace(match[1]);
+ unchecked.emplace((format("{%1%:%2%}" % LSOF % n++).str(), match[1]);
}
} catch (ExecError & e) {
/* lsof not installed, lsof failed */
@@ -473,21 +475,20 @@ PathSet LocalStore::findRuntimeRoots()
#endif
#if defined(__linux__)
- readFileRoots("/proc/sys/kernel/modprobe", paths);
- readFileRoots("/proc/sys/kernel/fbsplash", paths);
- readFileRoots("/proc/sys/kernel/poweroff_cmd", paths);
+ readFileRoots("/proc/sys/kernel/modprobe", unchecked);
+ readFileRoots("/proc/sys/kernel/fbsplash", unchecked);
+ readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked);
#endif
- for (auto & i : paths)
- if (isInStore(i)) {
- Path path = toStorePath(i);
- if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) {
+ for (auto & root : unchecked) {
+ if (isInStore(root.second)) {
+ Path path = toStorePath(root.second);
+ if (isStorePath(path) && isValidPath(path)) {
debug(format("got additional root '%1%'") % path);
- roots.insert(path);
+ roots.emplace(root.first, path);
}
}
-
- return roots;
+ }
}