Merge branch 'wait-for-builders' of https://github.com/serokell/nix
This commit is contained in:
commit
0ed946aa61
|
@ -507,6 +507,7 @@ private:
|
||||||
Path fnUserLock;
|
Path fnUserLock;
|
||||||
AutoCloseFD fdUserLock;
|
AutoCloseFD fdUserLock;
|
||||||
|
|
||||||
|
bool isEnabled;
|
||||||
string user;
|
string user;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
@ -522,7 +523,9 @@ public:
|
||||||
uid_t getGID() { assert(gid); return gid; }
|
uid_t getGID() { assert(gid); return gid; }
|
||||||
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
|
std::vector<gid_t> getSupplementaryGIDs() { return supplementaryGIDs; }
|
||||||
|
|
||||||
bool enabled() { return uid != 0; }
|
bool findFreeUser();
|
||||||
|
|
||||||
|
bool enabled() { return isEnabled; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -530,6 +533,14 @@ public:
|
||||||
UserLock::UserLock()
|
UserLock::UserLock()
|
||||||
{
|
{
|
||||||
assert(settings.buildUsersGroup != "");
|
assert(settings.buildUsersGroup != "");
|
||||||
|
createDirs(settings.nixStateDir + "/userpool");
|
||||||
|
/* Mark that user is not enabled by default */
|
||||||
|
uid = 0;
|
||||||
|
isEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UserLock::findFreeUser() {
|
||||||
|
if (enabled()) return true;
|
||||||
|
|
||||||
/* Get the members of the build-users-group. */
|
/* Get the members of the build-users-group. */
|
||||||
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
|
||||||
|
@ -559,7 +570,6 @@ UserLock::UserLock()
|
||||||
throw Error(format("the user '%1%' in the group '%2%' does not exist")
|
throw Error(format("the user '%1%' in the group '%2%' does not exist")
|
||||||
% i % settings.buildUsersGroup);
|
% i % settings.buildUsersGroup);
|
||||||
|
|
||||||
createDirs(settings.nixStateDir + "/userpool");
|
|
||||||
|
|
||||||
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
fnUserLock = (format("%1%/userpool/%2%") % settings.nixStateDir % pw->pw_uid).str();
|
||||||
|
|
||||||
|
@ -590,16 +600,13 @@ UserLock::UserLock()
|
||||||
supplementaryGIDs.resize(ngroups);
|
supplementaryGIDs.resize(ngroups);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return;
|
isEnabled = true;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
throw Error(format("all build users are currently in use; "
|
|
||||||
"consider creating additional users and adding them to the '%1%' group")
|
|
||||||
% settings.buildUsersGroup);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void UserLock::kill()
|
void UserLock::kill()
|
||||||
{
|
{
|
||||||
killUser(uid);
|
killUser(uid);
|
||||||
|
@ -928,6 +935,7 @@ private:
|
||||||
void closureRepaired();
|
void closureRepaired();
|
||||||
void inputsRealised();
|
void inputsRealised();
|
||||||
void tryToBuild();
|
void tryToBuild();
|
||||||
|
void tryLocalBuild();
|
||||||
void buildDone();
|
void buildDone();
|
||||||
|
|
||||||
/* Is the build hook willing to perform the build? */
|
/* Is the build hook willing to perform the build? */
|
||||||
|
@ -999,6 +1007,8 @@ private:
|
||||||
Goal::amDone(result);
|
Goal::amDone(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void started();
|
||||||
|
|
||||||
void done(BuildResult::Status status, const string & msg = "");
|
void done(BuildResult::Status status, const string & msg = "");
|
||||||
|
|
||||||
StorePathSet exportReferences(const StorePathSet & storePaths);
|
StorePathSet exportReferences(const StorePathSet & storePaths);
|
||||||
|
@ -1386,6 +1396,19 @@ void DerivationGoal::inputsRealised()
|
||||||
result = BuildResult();
|
result = BuildResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DerivationGoal::started() {
|
||||||
|
auto msg = fmt(
|
||||||
|
buildMode == bmRepair ? "repairing outputs of '%s'" :
|
||||||
|
buildMode == bmCheck ? "checking outputs of '%s'" :
|
||||||
|
nrRounds > 1 ? "building '%s' (round %d/%d)" :
|
||||||
|
"building '%s'", worker.store.printStorePath(drvPath), curRound, nrRounds);
|
||||||
|
fmt("building '%s'", worker.store.printStorePath(drvPath));
|
||||||
|
if (hook) msg += fmt(" on '%s'", machineName);
|
||||||
|
act = std::make_unique<Activity>(*logger, lvlInfo, actBuild, msg,
|
||||||
|
Logger::Fields{worker.store.printStorePath(drvPath), hook ? machineName : "", curRound, nrRounds});
|
||||||
|
mcRunningBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.runningBuilds);
|
||||||
|
worker.updateProgress();
|
||||||
|
}
|
||||||
|
|
||||||
void DerivationGoal::tryToBuild()
|
void DerivationGoal::tryToBuild()
|
||||||
{
|
{
|
||||||
|
@ -1437,20 +1460,6 @@ void DerivationGoal::tryToBuild()
|
||||||
supported for local builds. */
|
supported for local builds. */
|
||||||
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
|
bool buildLocally = buildMode != bmNormal || parsedDrv->willBuildLocally();
|
||||||
|
|
||||||
auto started = [&]() {
|
|
||||||
auto msg = fmt(
|
|
||||||
buildMode == bmRepair ? "repairing outputs of '%s'" :
|
|
||||||
buildMode == bmCheck ? "checking outputs of '%s'" :
|
|
||||||
nrRounds > 1 ? "building '%s' (round %d/%d)" :
|
|
||||||
"building '%s'", worker.store.printStorePath(drvPath), curRound, nrRounds);
|
|
||||||
fmt("building '%s'", worker.store.printStorePath(drvPath));
|
|
||||||
if (hook) msg += fmt(" on '%s'", machineName);
|
|
||||||
act = std::make_unique<Activity>(*logger, lvlInfo, actBuild, msg,
|
|
||||||
Logger::Fields{worker.store.printStorePath(drvPath), hook ? machineName : "", curRound, nrRounds});
|
|
||||||
mcRunningBuilds = std::make_unique<MaintainCount<uint64_t>>(worker.runningBuilds);
|
|
||||||
worker.updateProgress();
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Is the build hook willing to accept this job? */
|
/* Is the build hook willing to accept this job? */
|
||||||
if (!buildLocally) {
|
if (!buildLocally) {
|
||||||
switch (tryBuildHook()) {
|
switch (tryBuildHook()) {
|
||||||
|
@ -1483,6 +1492,34 @@ void DerivationGoal::tryToBuild()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = &DerivationGoal::tryLocalBuild;
|
||||||
|
worker.wakeUp(shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DerivationGoal::tryLocalBuild() {
|
||||||
|
|
||||||
|
/* If `build-users-group' is not empty, then we have to build as
|
||||||
|
one of the members of that group. */
|
||||||
|
if (settings.buildUsersGroup != "" && getuid() == 0) {
|
||||||
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
|
if (!buildUser) buildUser = std::make_unique<UserLock>();
|
||||||
|
|
||||||
|
if (buildUser->findFreeUser()) {
|
||||||
|
/* Make sure that no other processes are executing under this
|
||||||
|
uid. */
|
||||||
|
buildUser->kill();
|
||||||
|
} else {
|
||||||
|
debug("waiting for build users");
|
||||||
|
worker.waitForAWhile(shared_from_this());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Don't know how to block the creation of setuid/setgid
|
||||||
|
binaries on this platform. */
|
||||||
|
throw Error("build users are not supported on this platform for security reasons");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
/* Okay, we have to build. */
|
/* Okay, we have to build. */
|
||||||
|
@ -1943,22 +1980,6 @@ void DerivationGoal::startBuilder()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If `build-users-group' is not empty, then we have to build as
|
|
||||||
one of the members of that group. */
|
|
||||||
if (settings.buildUsersGroup != "" && getuid() == 0) {
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
|
||||||
buildUser = std::make_unique<UserLock>();
|
|
||||||
|
|
||||||
/* Make sure that no other processes are executing under this
|
|
||||||
uid. */
|
|
||||||
buildUser->kill();
|
|
||||||
#else
|
|
||||||
/* Don't know how to block the creation of setuid/setgid
|
|
||||||
binaries on this platform. */
|
|
||||||
throw Error("build users are not supported on this platform for security reasons");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a temporary directory where the build will take
|
/* Create a temporary directory where the build will take
|
||||||
place. */
|
place. */
|
||||||
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
|
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
|
||||||
|
@ -4820,7 +4841,7 @@ void Worker::waitForInput()
|
||||||
if (!waitingForAWhile.empty()) {
|
if (!waitingForAWhile.empty()) {
|
||||||
useTimeout = true;
|
useTimeout = true;
|
||||||
if (lastWokenUp == steady_time_point::min())
|
if (lastWokenUp == steady_time_point::min())
|
||||||
printError("waiting for locks or build slots...");
|
printError("waiting for locks, build slots or build users...");
|
||||||
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
|
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
|
||||||
timeout = std::max(1L,
|
timeout = std::max(1L,
|
||||||
(long) std::chrono::duration_cast<std::chrono::seconds>(
|
(long) std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
|
Loading…
Reference in a new issue