67 lines
2.2 KiB
C++
67 lines
2.2 KiB
C++
#include "cgroup.hpp"
|
|||
|
|
|
||
|
|
#include <unistd.h>
|
||
|
|
|
||
|
|
#include <chrono>
|
||
|
|
#include <thread>
|
||
|
|
|
||
|
|
#include "spec.hpp"
|
||
|
|
#include "util.hpp"
|
||
|
|
|
||
|
|
namespace fs = std::filesystem;
|
||
|
|
|
||
|
|
namespace doos {
|
||
|
|
|
||
|
|
std::unique_ptr<Cgroup> Cgroup::create(const std::string& name, std::string& whyNot) {
|
||
|
|
try {
|
||
|
|
std::string self = fsutil::readFile("/proc/self/cgroup");
|
||
|
|
std::string marker = "user@" + std::to_string(::geteuid()) + ".service";
|
||
|
|
auto at = self.find(marker);
|
||
|
|
if (self.rfind("0::", 0) != 0 || at == std::string::npos) {
|
||
|
|
whyNot = "no cgroup v2 delegated to the user manager (" + marker + " not found)";
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
fs::path base = fs::path("/sys/fs/cgroup") / self.substr(3, at + marker.size() - 3).substr(1);
|
||
|
|
fs::path dir = base / std::string(spec::kCgroupDir);
|
||
|
|
std::error_code ec;
|
||
|
|
fs::create_directory(dir, ec);
|
||
|
|
if (ec && ec != std::errc::file_exists) {
|
||
|
|
whyNot = "cannot create " + dir.string() + ": " + ec.message();
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
fs::path leaf = dir / name;
|
||
|
|
fs::create_directory(leaf, ec);
|
||
|
|
if (ec && ec != std::errc::file_exists) {
|
||
|
|
whyNot = "cannot create " + leaf.string() + ": " + ec.message();
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
if (::access((leaf / "cgroup.freeze").c_str(), W_OK) != 0) {
|
||
|
|
whyNot = "cgroup.freeze not writable in " + leaf.string();
|
||
|
|
fs::remove(leaf, ec);
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
return std::unique_ptr<Cgroup>(new Cgroup(leaf));
|
||
|
|
} catch (const std::exception& e) {
|
||
|
|
whyNot = e.what();
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Cgroup::~Cgroup() {
|
||
|
|
// Processes die with the container; give the kernel a moment to empty the group, then remove it.
|
||
|
|
for (int i = 0; i < 20; ++i) {
|
||
|
|
std::error_code ec;
|
||
|
|
if (fs::remove(dir_, ec)) return;
|
||
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(25));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void Cgroup::add(pid_t pid) const { fsutil::writeFile(dir_ / "cgroup.procs", std::to_string(pid)); }
|
||
|
|
|
||
|
|
void Cgroup::freeze(bool on) const {
|
||
|
|
fsutil::writeFile(dir_ / "cgroup.freeze", on ? "1" : "0");
|
||
|
|
frozen_ = on;
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace doos
|