mirror of
https://github.com/NixOS/nix
synced 2025-06-29 02:11:15 +02:00
Separate cgroup support from auto-uid-allocation
The new experimental feature 'cgroups' enables the use of cgroups for all builds. This allows better containment and enables setting resource limits and getting some build stats.
This commit is contained in:
parent
f1ab082ac4
commit
128910ba23
6 changed files with 93 additions and 108 deletions
|
@ -1,7 +1,6 @@
|
|||
#include "lock.hh"
|
||||
#include "globals.hh"
|
||||
#include "pathlocks.hh"
|
||||
#include "cgroup.hh"
|
||||
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
|
@ -15,11 +14,6 @@ struct SimpleUserLock : UserLock
|
|||
gid_t gid;
|
||||
std::vector<gid_t> supplementaryGIDs;
|
||||
|
||||
void kill() override
|
||||
{
|
||||
killUser(uid);
|
||||
}
|
||||
|
||||
uid_t getUID() override { assert(uid); return uid; }
|
||||
uid_t getUIDCount() override { return 1; }
|
||||
gid_t getGID() override { assert(gid); return gid; }
|
||||
|
@ -116,32 +110,6 @@ struct AutoUserLock : UserLock
|
|||
AutoCloseFD fdUserLock;
|
||||
uid_t firstUid = 0;
|
||||
uid_t nrIds = 1;
|
||||
#if __linux__
|
||||
std::optional<Path> cgroup;
|
||||
#endif
|
||||
|
||||
~AutoUserLock()
|
||||
{
|
||||
#if __linux__
|
||||
// Get rid of our cgroup, ignoring errors.
|
||||
if (cgroup) rmdir(cgroup->c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
void kill() override
|
||||
{
|
||||
#if __linux__
|
||||
if (cgroup) {
|
||||
destroyCgroup(*cgroup);
|
||||
if (mkdir(cgroup->c_str(), 0755) == -1)
|
||||
throw SysError("creating cgroup '%s'", *cgroup);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
assert(firstUid);
|
||||
killUser(firstUid);
|
||||
}
|
||||
}
|
||||
|
||||
uid_t getUID() override { assert(firstUid); return firstUid; }
|
||||
|
||||
|
@ -183,55 +151,16 @@ struct AutoUserLock : UserLock
|
|||
throw SysError("opening user lock '%s'", fnUserLock);
|
||||
|
||||
if (lockFile(fd.get(), ltWrite, false)) {
|
||||
auto s = drainFD(fd.get());
|
||||
|
||||
#if __linux__
|
||||
if (s != "") {
|
||||
/* Kill the old cgroup, to ensure there are no
|
||||
processes left over from an interrupted build. */
|
||||
destroyCgroup(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ftruncate(fd.get(), 0) == -1)
|
||||
throw Error("truncating user lock");
|
||||
|
||||
auto lock = std::make_unique<AutoUserLock>();
|
||||
lock->fdUserLock = std::move(fd);
|
||||
lock->firstUid = settings.startId + i * maxIdsPerBuild;
|
||||
lock->nrIds = nrIds;
|
||||
|
||||
#if __linux__
|
||||
if (nrIds > 1) {
|
||||
auto ourCgroups = getCgroups("/proc/self/cgroup");
|
||||
auto ourCgroup = ourCgroups[""];
|
||||
if (ourCgroup == "")
|
||||
throw Error("cannot determine cgroup name from /proc/self/cgroup");
|
||||
|
||||
auto ourCgroupPath = canonPath("/sys/fs/cgroup/" + ourCgroup);
|
||||
|
||||
if (!pathExists(ourCgroupPath))
|
||||
throw Error("expected cgroup directory '%s'", ourCgroupPath);
|
||||
|
||||
lock->cgroup = fmt("%s/nix-build-%d", ourCgroupPath, lock->firstUid);
|
||||
|
||||
/* Record the cgroup in the lock file. This ensures that
|
||||
if we subsequently get executed under a different parent
|
||||
cgroup, we kill the previous cgroup first. */
|
||||
writeFull(lock->fdUserLock.get(), *lock->cgroup);
|
||||
}
|
||||
#endif
|
||||
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
std::optional<Path> getCgroup() override { return cgroup; }
|
||||
#endif
|
||||
};
|
||||
|
||||
std::unique_ptr<UserLock> acquireUserLock(uid_t nrIds)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue