Skip to content

Commit

Permalink
Destroy the cgroup prior to building
Browse files Browse the repository at this point in the history
  • Loading branch information
edolstra committed May 18, 2020
1 parent 135ef6c commit fa49bfa
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 4 deletions.
8 changes: 4 additions & 4 deletions src/libstore/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "machines.hh"
#include "daemon.hh"
#include "worker-protocol.hh"
#include "cgroup.hh"

#include <algorithm>
#include <iostream>
Expand Down Expand Up @@ -2372,14 +2373,13 @@ void DerivationGoal::startBuilder()
auto hostCgroup = canonPath("/sys/fs/cgroup/" + name + "/" + cgroup);

if (!pathExists(hostCgroup))
throw Error("expected unified cgroup directory '%s'", hostCgroup);
throw Error("expected cgroup directory '%s'", hostCgroup);

auto childCgroup = fmt("%s/nix-%d", hostCgroup, buildUser->getUID());

// FIXME: if the cgroup already exists, kill all processes
// in it and destroy it.
destroyCgroup(childCgroup);

if (mkdir(childCgroup.c_str(), 0755) == -1 && errno != EEXIST)
if (mkdir(childCgroup.c_str(), 0755) == -1)
throw SysError("creating cgroup '%s'", childCgroup);

chownToBuilder(childCgroup);
Expand Down
49 changes: 49 additions & 0 deletions src/libstore/cgroup.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#if __linux__

#include "cgroup.hh"
#include "util.hh"

#include <chrono>

#include <dirent.h>

namespace nix {

void destroyCgroup(const Path & cgroup)
{
for (auto & entry : readDirectory(cgroup)) {
if (entry.type != DT_DIR) continue;
destroyCgroup(cgroup + "/" + entry.name);
}

int round = 1;

while (true) {
auto pids = tokenizeString<std::vector<std::string>>(readFile(cgroup + "/cgroup.procs"));

if (pids.empty()) break;

if (round > 20)
throw Error("cannot kill cgroup '%s'", cgroup);

for (auto & pid_s : pids) {
pid_t pid;
if (!string2Int(pid_s, pid)) throw Error("invalid pid '%s'", pid);
// FIXME: pid wraparound
if (kill(pid, SIGKILL) == -1 && errno != ESRCH)
throw SysError("killing member %d of cgroup '%s'", pid, cgroup);
}

auto sleep = std::chrono::milliseconds((int) std::pow(2.0, std::min(round, 10)));
printError("waiting for %d ms for cgroup '%s' to become empty", sleep.count(), cgroup);
std::this_thread::sleep_for(sleep);
round++;
}

if (rmdir(cgroup.c_str()) == -1)
throw SysError("deleting cgroup '%s'", cgroup);
}

}

#endif
13 changes: 13 additions & 0 deletions src/libstore/cgroup.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#if __linux__

#include "types.hh"

namespace nix {

void destroyCgroup(const Path & cgroup);

}

#endif

0 comments on commit fa49bfa

Please sign in to comment.