detail memory roots
This commit is contained in:
parent
5886bc5996
commit
43331d6344
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue