Merge pull request #7394 from edolstra/fix-7268

Lower verbosity of exceptions in getMaxCPU()
This commit is contained in:
Eelco Dolstra 2022-12-02 17:02:32 +01:00 committed by GitHub
commit c582150360
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 41 additions and 41 deletions

View file

@ -409,12 +409,16 @@ void LocalDerivationGoal::startBuilder()
#if __linux__ #if __linux__
settings.requireExperimentalFeature(Xp::Cgroups); settings.requireExperimentalFeature(Xp::Cgroups);
auto cgroupFS = getCgroupFS();
if (!cgroupFS)
throw Error("cannot determine the cgroups file system");
auto ourCgroups = getCgroups("/proc/self/cgroup"); auto ourCgroups = getCgroups("/proc/self/cgroup");
auto ourCgroup = ourCgroups[""]; auto ourCgroup = ourCgroups[""];
if (ourCgroup == "") if (ourCgroup == "")
throw Error("cannot determine cgroup name from /proc/self/cgroup"); throw Error("cannot determine cgroup name from /proc/self/cgroup");
auto ourCgroupPath = canonPath("/sys/fs/cgroup/" + ourCgroup); auto ourCgroupPath = canonPath(*cgroupFS + "/" + ourCgroup);
if (!pathExists(ourCgroupPath)) if (!pathExists(ourCgroupPath))
throw Error("expected cgroup directory '%s'", ourCgroupPath); throw Error("expected cgroup directory '%s'", ourCgroupPath);

View file

@ -2,6 +2,7 @@
#include "cgroup.hh" #include "cgroup.hh"
#include "util.hh" #include "util.hh"
#include "finally.hh"
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
@ -10,9 +11,25 @@
#include <thread> #include <thread>
#include <dirent.h> #include <dirent.h>
#include <mntent.h>
namespace nix { namespace nix {
std::optional<Path> getCgroupFS()
{
static auto res = [&]() -> std::optional<Path> {
auto fp = fopen("/proc/mounts", "r");
if (!fp) return std::nullopt;
Finally delFP = [&]() { fclose(fp); };
while (auto ent = getmntent(fp))
if (std::string_view(ent->mnt_type) == "cgroup2")
return ent->mnt_dir;
return std::nullopt;
}();
return res;
}
// FIXME: obsolete, check for cgroup2 // FIXME: obsolete, check for cgroup2
std::map<std::string, std::string> getCgroups(const Path & cgroupFile) std::map<std::string, std::string> getCgroups(const Path & cgroupFile)
{ {

View file

@ -9,6 +9,8 @@
namespace nix { namespace nix {
std::optional<Path> getCgroupFS();
std::map<std::string, std::string> getCgroups(const Path & cgroupFile); std::map<std::string, std::string> getCgroups(const Path & cgroupFile);
struct CgroupStats struct CgroupStats

View file

@ -2,6 +2,7 @@
#include "sync.hh" #include "sync.hh"
#include "finally.hh" #include "finally.hh"
#include "serialise.hh" #include "serialise.hh"
#include "cgroup.hh"
#include <array> #include <array>
#include <cctype> #include <cctype>
@ -36,7 +37,6 @@
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <mntent.h>
#include <cmath> #include <cmath>
#endif #endif
@ -727,45 +727,22 @@ unsigned int getMaxCPU()
{ {
#if __linux__ #if __linux__
try { try {
FILE *fp = fopen("/proc/mounts", "r"); auto cgroupFS = getCgroupFS();
if (!fp) if (!cgroupFS) return 0;
return 0;
Strings cgPathParts; auto cgroups = getCgroups("/proc/self/cgroupp");
auto cgroup = cgroups[""];
if (cgroup == "") return 0;
struct mntent *ent; auto cpuFile = *cgroupFS + "/" + cgroup + "/cpu.max";
while ((ent = getmntent(fp))) {
std::string mountType, mountPath;
mountType = ent->mnt_type; auto cpuMax = readFile(cpuFile);
mountPath = ent->mnt_dir; auto cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " \n");
auto quota = cpuMaxParts[0];
if (mountType == "cgroup2") { auto period = cpuMaxParts[1];
cgPathParts.push_back(mountPath); if (quota != "max")
break; return std::ceil(std::stoi(quota) / std::stof(period));
} } catch (Error &) { ignoreException(lvlDebug); }
}
fclose(fp);
if (cgPathParts.size() > 0 && pathExists("/proc/self/cgroup")) {
std::string currentCgroup = readFile("/proc/self/cgroup");
Strings cgValues = tokenizeString<Strings>(currentCgroup, ":");
cgPathParts.push_back(trim(cgValues.back(), "\n"));
cgPathParts.push_back("cpu.max");
std::string fullCgPath = canonPath(concatStringsSep("/", cgPathParts));
if (pathExists(fullCgPath)) {
std::string cpuMax = readFile(fullCgPath);
std::vector<std::string> cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " ");
std::string quota = cpuMaxParts[0];
std::string period = trim(cpuMaxParts[1], "\n");
if (quota != "max")
return std::ceil(std::stoi(quota) / std::stof(period));
}
}
} catch (Error &) { ignoreException(); }
#endif #endif
return 0; return 0;
@ -1427,7 +1404,7 @@ std::string shellEscape(const std::string_view s)
} }
void ignoreException() void ignoreException(Verbosity lvl)
{ {
/* Make sure no exceptions leave this function. /* Make sure no exceptions leave this function.
printError() also throws when remote is closed. */ printError() also throws when remote is closed. */
@ -1435,7 +1412,7 @@ void ignoreException()
try { try {
throw; throw;
} catch (std::exception & e) { } catch (std::exception & e) {
printError("error (ignored): %1%", e.what()); printMsg(lvl, "error (ignored): %1%", e.what());
} }
} catch (...) { } } catch (...) { }
} }

View file

@ -528,7 +528,7 @@ std::string shellEscape(const std::string_view s);
/* Exception handling in destructors: print an error message, then /* Exception handling in destructors: print an error message, then
ignore the exception. */ ignore the exception. */
void ignoreException(); void ignoreException(Verbosity lvl = lvlError);