Make findRuntimeRoots() more resilient to disappearing processes
I saw this random failure in https://hydra.nixos.org/build/211811692: error: opening /proc/15307/fd: No such process while running nix-collect-garbage in a readfile-context.sh. This is because we're not handling ESRCH errors reading /proc/<pid>/fd. So just move the read inside the try/catch where we do handle it.
This commit is contained in:
parent
c44750982d
commit
4f3a4b732c
1 changed files with 22 additions and 22 deletions
|
@ -371,29 +371,29 @@ void LocalStore::findRuntimeRoots(Roots & roots, bool censor)
|
||||||
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(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
|
|
||||||
readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
|
|
||||||
|
|
||||||
auto fdStr = fmt("/proc/%s/fd", ent->d_name);
|
|
||||||
auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
|
|
||||||
if (!fdDir) {
|
|
||||||
if (errno == ENOENT || errno == EACCES)
|
|
||||||
continue;
|
|
||||||
throw SysError("opening %1%", fdStr);
|
|
||||||
}
|
|
||||||
struct dirent * fd_ent;
|
|
||||||
while (errno = 0, fd_ent = readdir(fdDir.get())) {
|
|
||||||
if (fd_ent->d_name[0] != '.')
|
|
||||||
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
|
|
||||||
}
|
|
||||||
if (errno) {
|
|
||||||
if (errno == ESRCH)
|
|
||||||
continue;
|
|
||||||
throw SysError("iterating /proc/%1%/fd", ent->d_name);
|
|
||||||
}
|
|
||||||
fdDir.reset();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
readProcLink(fmt("/proc/%s/exe" ,ent->d_name), unchecked);
|
||||||
|
readProcLink(fmt("/proc/%s/cwd", ent->d_name), unchecked);
|
||||||
|
|
||||||
|
auto fdStr = fmt("/proc/%s/fd", ent->d_name);
|
||||||
|
auto fdDir = AutoCloseDir(opendir(fdStr.c_str()));
|
||||||
|
if (!fdDir) {
|
||||||
|
if (errno == ENOENT || errno == EACCES)
|
||||||
|
continue;
|
||||||
|
throw SysError("opening %1%", fdStr);
|
||||||
|
}
|
||||||
|
struct dirent * fd_ent;
|
||||||
|
while (errno = 0, fd_ent = readdir(fdDir.get())) {
|
||||||
|
if (fd_ent->d_name[0] != '.')
|
||||||
|
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
|
||||||
|
}
|
||||||
|
if (errno) {
|
||||||
|
if (errno == ESRCH)
|
||||||
|
continue;
|
||||||
|
throw SysError("iterating /proc/%1%/fd", ent->d_name);
|
||||||
|
}
|
||||||
|
fdDir.reset();
|
||||||
|
|
||||||
auto mapFile = fmt("/proc/%s/maps", ent->d_name);
|
auto mapFile = fmt("/proc/%s/maps", ent->d_name);
|
||||||
auto mapLines = tokenizeString<std::vector<std::string>>(readFile(mapFile), "\n");
|
auto mapLines = tokenizeString<std::vector<std::string>>(readFile(mapFile), "\n");
|
||||||
for (const auto & line : mapLines) {
|
for (const auto & line : mapLines) {
|
||||||
|
|
Loading…
Reference in a new issue