detail memory roots

This commit is contained in:
Guillaume Maudoux 2019-02-27 23:32:12 +01:00
parent 5886bc5996
commit 43331d6344
2 changed files with 32 additions and 31 deletions

View file

@ -333,9 +333,7 @@ Roots LocalStore::findRootsNoTemp()
NIX_ROOT_FINDER environment variable. This is typically used NIX_ROOT_FINDER environment variable. This is typically used
to add running programs to the set of roots (to prevent them to add running programs to the set of roots (to prevent them
from being garbage collected). */ from being garbage collected). */
size_t n = 0; findRuntimeRoots(roots);
for (auto & root : findRuntimeRoots())
roots[fmt("{memory:%d}", n++)] = root;
return roots; return roots;
} }
@ -357,8 +355,7 @@ Roots LocalStore::findRoots()
return roots; return roots;
} }
static void readProcLink(const string & file, Roots & roots)
static void readProcLink(const string & file, StringSet & paths)
{ {
/* 64 is the starting buffer size gnu readlink uses... */ /* 64 is the starting buffer size gnu readlink uses... */
auto bufsiz = ssize_t{64}; auto bufsiz = ssize_t{64};
@ -377,7 +374,7 @@ try_again:
goto try_again; goto try_again;
} }
if (res > 0 && buf[0] == '/') if (res > 0 && buf[0] == '/')
paths.emplace(static_cast<char *>(buf), res); roots.emplace(file, std::string(static_cast<char *>(buf), res));
return; return;
} }
@ -387,20 +384,20 @@ static string quoteRegexChars(const string & raw)
return std::regex_replace(raw, specialRegex, R"(\$&)"); return std::regex_replace(raw, specialRegex, R"(\$&)");
} }
static void readFileRoots(const char * path, StringSet & paths) static void readFileRoots(const char * path, Roots & roots)
{ {
try { try {
paths.emplace(readFile(path)); roots.emplace(path, readFile(path));
} catch (SysError & e) { } catch (SysError & e) {
if (e.errNo != ENOENT && e.errNo != EACCES) if (e.errNo != ENOENT && e.errNo != EACCES)
throw; throw;
} }
} }
PathSet LocalStore::findRuntimeRoots() void LocalStore::findRuntimeRoots(Roots & roots)
{ {
PathSet roots; Roots unchecked;
StringSet paths;
auto procDir = AutoCloseDir{opendir("/proc")}; auto procDir = AutoCloseDir{opendir("/proc")};
if (procDir) { if (procDir) {
struct dirent * ent; struct dirent * ent;
@ -410,8 +407,8 @@ PathSet LocalStore::findRuntimeRoots()
while (errno = 0, ent = readdir(procDir.get())) { while (errno = 0, ent = readdir(procDir.get())) {
checkInterrupt(); checkInterrupt();
if (std::regex_match(ent->d_name, digitsRegex)) { if (std::regex_match(ent->d_name, digitsRegex)) {
readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), paths); readProcLink((format("/proc/%1%/exe") % ent->d_name).str(), unchecked);
readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), paths); readProcLink((format("/proc/%1%/cwd") % ent->d_name).str(), unchecked);
auto fdStr = (format("/proc/%1%/fd") % ent->d_name).str(); auto fdStr = (format("/proc/%1%/fd") % ent->d_name).str();
auto fdDir = AutoCloseDir(opendir(fdStr.c_str())); auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
@ -423,7 +420,7 @@ PathSet LocalStore::findRuntimeRoots()
struct dirent * fd_ent; struct dirent * fd_ent;
while (errno = 0, fd_ent = readdir(fdDir.get())) { while (errno = 0, fd_ent = readdir(fdDir.get())) {
if (fd_ent->d_name[0] != '.') { 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) { if (errno) {
@ -434,18 +431,22 @@ PathSet LocalStore::findRuntimeRoots()
fdDir.reset(); fdDir.reset();
try { try {
auto mapLines = auto mapFile = (format("/proc/%1%/maps") % ent->d_name).str();
tokenizeString<std::vector<string>>(readFile((format("/proc/%1%/maps") % ent->d_name).str(), true), "\n"); auto mapLines = tokenizeString<std::vector<string>>(readFile(mapFile, true), "\n");
int n = 0;
for (const auto& line : mapLines) { for (const auto& line : mapLines) {
n++;
auto match = std::smatch{}; auto match = std::smatch{};
if (std::regex_match(line, match, mapRegex)) 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{}; auto env_end = std::sregex_iterator{};
n = 0;
for (auto i = std::sregex_iterator{envString.begin(), envString.end(), storePathRegex}; i != env_end; ++i) 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) { } catch (SysError & e) {
if (errno == ENOENT || errno == EACCES || errno == ESRCH) if (errno == ENOENT || errno == EACCES || errno == ESRCH)
continue; continue;
@ -462,10 +463,11 @@ PathSet LocalStore::findRuntimeRoots()
std::regex lsofRegex(R"(^n(/.*)$)"); std::regex lsofRegex(R"(^n(/.*)$)");
auto lsofLines = auto lsofLines =
tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n"); tokenizeString<std::vector<string>>(runProgram(LSOF, true, { "-n", "-w", "-F", "n" }), "\n");
int n = 0;
for (const auto & line : lsofLines) { for (const auto & line : lsofLines) {
std::smatch match; std::smatch match;
if (std::regex_match(line, match, lsofRegex)) if (std::regex_match(line, match, lsofRegex))
paths.emplace(match[1]); unchecked.emplace((format("{%1%:%2%}" % LSOF % n++).str(), match[1]);
} }
} catch (ExecError & e) { } catch (ExecError & e) {
/* lsof not installed, lsof failed */ /* lsof not installed, lsof failed */
@ -473,21 +475,20 @@ PathSet LocalStore::findRuntimeRoots()
#endif #endif
#if defined(__linux__) #if defined(__linux__)
readFileRoots("/proc/sys/kernel/modprobe", paths); readFileRoots("/proc/sys/kernel/modprobe", unchecked);
readFileRoots("/proc/sys/kernel/fbsplash", paths); readFileRoots("/proc/sys/kernel/fbsplash", unchecked);
readFileRoots("/proc/sys/kernel/poweroff_cmd", paths); readFileRoots("/proc/sys/kernel/poweroff_cmd", unchecked);
#endif #endif
for (auto & i : paths) for (auto & root : unchecked) {
if (isInStore(i)) { if (isInStore(root.second)) {
Path path = toStorePath(i); Path path = toStorePath(root.second);
if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) { if (isStorePath(path) && isValidPath(path)) {
debug(format("got additional root '%1%'") % path); debug(format("got additional root '%1%'") % path);
roots.insert(path); roots.emplace(root.first, path);
}
} }
} }
return roots;
} }

View file

@ -269,7 +269,7 @@ private:
Roots findRootsNoTemp(); Roots findRootsNoTemp();
PathSet findRuntimeRoots(); void findRuntimeRoots(Roots & roots);
void removeUnusedLinks(const GCState & state); void removeUnusedLinks(const GCState & state);