Fix creation of cgroups

A commit in #14800 broke tests around creating cgroups due to incorrect
path handling logic.
(See https://hydra.nixos.org/build/318367985/nixlog/11)

Fix that logic and represent cgroups as CanonPath.

Co-authored-by: John Ericson <John.Ericson@Obsidian.Systems>
Co-authored-by: Sergei Zimmerman <sergei@zimmerman.foo>
This commit is contained in:
Artemis Tosini
2026-01-05 19:41:01 +00:00
parent 31bffd3c78
commit 357a45253c
5 changed files with 14 additions and 13 deletions

View File

@@ -226,18 +226,18 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
/* If we're running from the daemon, then this will return the
root cgroup of the service. Otherwise, it will return the
current cgroup. */
auto rootCgroup = getRootCgroup();
auto cgroupFS = getCgroupFS();
if (!cgroupFS)
throw Error("cannot determine the cgroups file system");
auto rootCgroupPath = canonPath((*cgroupFS / rootCgroup).native());
auto rootCgroupPath = *cgroupFS / getRootCgroup().rel();
if (!pathExists(rootCgroupPath))
throw Error("expected cgroup directory '%s'", rootCgroupPath);
static std::atomic<unsigned int> counter{0};
cgroup = buildUser ? fmt("%s/nix-build-uid-%d", rootCgroupPath, buildUser->getUID())
: fmt("%s/nix-build-pid-%d-%d", rootCgroupPath, getpid(), counter++);
cgroup = rootCgroupPath
/ (buildUser ? fmt("nix-build-uid-%d", buildUser->getUID())
: fmt("nix-build-pid-%d-%d", getpid(), counter++));
debug("using cgroup %s", *cgroup);
@@ -248,7 +248,7 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
auto cgroupsDir = std::filesystem::path{settings.nixStateDir} / "cgroups";
createDirs(cgroupsDir);
auto cgroupFile = fmt("%s/%d", cgroupsDir, buildUser->getUID());
auto cgroupFile = cgroupsDir / std::to_string(buildUser->getUID());
if (pathExists(cgroupFile)) {
auto prevCgroup = readFile(cgroupFile);

View File

@@ -35,7 +35,7 @@ unsigned int getMaxCPU()
if (!cgroupFS)
return 0;
auto cpuFile = *cgroupFS + "/" + getCurrentCgroup() + "/cpu.max";
auto cpuFile = *cgroupFS / getCurrentCgroup().rel() / "cpu.max";
auto cpuMax = readFile(cpuFile);
auto cpuMaxParts = tokenizeString<std::vector<std::string>>(cpuMax, " \n");

View File

@@ -155,7 +155,7 @@ CgroupStats destroyCgroup(const std::filesystem::path & cgroup)
return destroyCgroup(cgroup, true);
}
std::string getCurrentCgroup()
CanonPath getCurrentCgroup()
{
auto cgroupFS = getCgroupFS();
if (!cgroupFS)
@@ -165,12 +165,12 @@ std::string getCurrentCgroup()
auto ourCgroup = ourCgroups[""];
if (ourCgroup == "")
throw Error("cannot determine cgroup name from /proc/self/cgroup");
return ourCgroup;
return CanonPath{ourCgroup};
}
std::string getRootCgroup()
CanonPath getRootCgroup()
{
static std::string rootCgroup = getCurrentCgroup();
static auto rootCgroup = getCurrentCgroup();
return rootCgroup;
}

View File

@@ -6,6 +6,7 @@
#include <filesystem>
#include "nix/util/types.hh"
#include "nix/util/canon-path.hh"
namespace nix {
@@ -31,13 +32,13 @@ CgroupStats getCgroupStats(const std::filesystem::path & cgroup);
*/
CgroupStats destroyCgroup(const std::filesystem::path & cgroup);
std::string getCurrentCgroup();
CanonPath getCurrentCgroup();
/**
* Get the cgroup that should be used as the parent when creating new
* sub-cgroups. The first time this is called, the current cgroup will be
* returned, and then all subsequent calls will return the original cgroup.
*/
std::string getRootCgroup();
CanonPath getRootCgroup();
} // namespace nix

View File

@@ -333,7 +333,7 @@ static void daemonLoop(std::optional<TrustedFlag> forceTrustClientOpt)
auto cgroupFS = getCgroupFS();
if (!cgroupFS)
throw Error("cannot determine the cgroups file system");
auto rootCgroupPath = canonPath(*cgroupFS + "/" + rootCgroup);
auto rootCgroupPath = *cgroupFS / rootCgroup.rel();
if (!pathExists(rootCgroupPath))
throw Error("expected cgroup directory '%s'", rootCgroupPath);
auto daemonCgroupPath = rootCgroupPath + "/nix-daemon";