1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-21 00:11:08 +01:00

Merge pull request #13860 from obsidiansystems/derivation-building-resources-code-cleanup

Derivation building resources code cleanup
This commit is contained in:
Jörg Thalheim 2025-09-01 20:22:30 +02:00 committed by GitHub
commit de7f137f31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 127 additions and 136 deletions

View file

@ -22,13 +22,6 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
PathsInChroot pathsInChroot;
void deleteTmpDir(bool force) override
{
autoDelChroot.reset(); /* this runs the destructor */
DerivationBuilderImpl::deleteTmpDir(force);
}
bool needsHashRewrite() override
{
return false;
@ -166,13 +159,13 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
return !needsHashRewrite() ? chrootRootDir + p : store.toRealPath(p);
}
void cleanupBuild() override
void cleanupBuild(bool force) override
{
DerivationBuilderImpl::cleanupBuild();
DerivationBuilderImpl::cleanupBuild(force);
/* Move paths out of the chroot for easier debugging of
build failures. */
if (buildMode == bmNormal)
if (!force && buildMode == bmNormal)
for (auto & [_, status] : initialOutputs) {
if (!status.known)
continue;
@ -182,6 +175,8 @@ struct ChrootDerivationBuilder : virtual DerivationBuilderImpl
if (pathExists(chrootRootDir + p))
std::filesystem::rename((chrootRootDir + p), p);
}
autoDelChroot.reset(); /* this runs the destructor */
}
std::pair<Path, Path> addDependencyPrep(const StorePath & path)

View file

@ -71,6 +71,11 @@ class DerivationBuilderImpl : public DerivationBuilder, public DerivationBuilder
{
protected:
/**
* The process ID of the builder.
*/
Pid pid;
LocalStore & store;
std::unique_ptr<DerivationBuilderCallbacks> miscMethods;
@ -86,6 +91,27 @@ public:
{
}
~DerivationBuilderImpl()
{
/* Careful: we should never ever throw an exception from a
destructor. */
try {
killChild();
} catch (...) {
ignoreExceptionInDestructor();
}
try {
stopDaemon();
} catch (...) {
ignoreExceptionInDestructor();
}
try {
cleanupBuild(false);
} catch (...) {
ignoreExceptionInDestructor();
}
}
protected:
/**
@ -192,7 +218,7 @@ public:
void startBuilder() override;
std::variant<BuildError, SingleDrvOutputs> unprepareBuild() override;
SingleDrvOutputs unprepareBuild() override;
protected:
@ -286,9 +312,11 @@ private:
*/
void startDaemon();
public:
void stopDaemon() override;
/**
* Stop the in-process nix daemon thread.
* @see startDaemon
*/
void stopDaemon();
protected:
@ -343,15 +371,25 @@ private:
*/
SingleDrvOutputs registerOutputs();
public:
void deleteTmpDir(bool force) override;
void killSandbox(bool getStats) override;
protected:
virtual void cleanupBuild();
/**
* Delete the temporary directory, if we have one.
*
* @param force We know the build suceeded, so don't attempt to
* preseve anything for debugging.
*/
virtual void cleanupBuild(bool force);
/**
* Kill any processes running under the build user UID or in the
* cgroup of the build.
*/
virtual void killSandbox(bool getStats);
public:
bool killChild() override;
private:
@ -414,6 +452,24 @@ void DerivationBuilderImpl::killSandbox(bool getStats)
}
}
bool DerivationBuilderImpl::killChild()
{
bool ret = pid != -1;
if (ret) {
/* If we're using a build user, then there is a tricky race
condition: if we kill the build user before the child has
done its setuid() to the build user uid, then it won't be
killed, and we'll potentially lock up in pid.wait(). So
also send a conventional kill to the child. */
::kill(-pid, SIGKILL); /* ignore the result */
killSandbox(true);
pid.wait();
}
return ret;
}
bool DerivationBuilderImpl::prepareBuild()
{
if (useBuildUsers()) {
@ -427,7 +483,7 @@ bool DerivationBuilderImpl::prepareBuild()
return true;
}
std::variant<BuildError, SingleDrvOutputs> DerivationBuilderImpl::unprepareBuild()
SingleDrvOutputs DerivationBuilderImpl::unprepareBuild()
{
// FIXME: get rid of this, rely on RAII.
Finally releaseBuildUser([&]() {
@ -476,56 +532,42 @@ std::variant<BuildError, SingleDrvOutputs> DerivationBuilderImpl::unprepareBuild
((double) buildResult.cpuSystem->count()) / 1000000);
}
bool diskFull = false;
/* Check the exit status. */
if (!statusOk(status)) {
try {
bool diskFull = decideWhetherDiskFull();
/* Check the exit status. */
if (!statusOk(status)) {
cleanupBuild(false);
diskFull |= decideWhetherDiskFull();
auto msg =
fmt("Cannot build '%s'.\n"
"Reason: " ANSI_RED "builder %s" ANSI_NORMAL ".",
Magenta(store.printStorePath(drvPath)),
statusToString(status));
cleanupBuild();
msg += showKnownOutputs(store, drv);
auto msg =
fmt("Cannot build '%s'.\n"
"Reason: " ANSI_RED "builder %s" ANSI_NORMAL ".",
Magenta(store.printStorePath(drvPath)),
statusToString(status));
miscMethods->appendLogTailErrorMsg(msg);
msg += showKnownOutputs(store, drv);
if (diskFull)
msg += "\nnote: build failure may have been caused by lack of free disk space";
miscMethods->appendLogTailErrorMsg(msg);
if (diskFull)
msg += "\nnote: build failure may have been caused by lack of free disk space";
throw BuildError(
!derivationType.isSandboxed() || diskFull ? BuildResult::TransientFailure
: BuildResult::PermanentFailure,
msg);
}
/* Compute the FS closure of the outputs and register them as
being valid. */
auto builtOutputs = registerOutputs();
/* Delete unused redirected outputs (when doing hash rewriting). */
for (auto & i : redirectedOutputs)
deletePath(store.Store::toRealPath(i.second));
deleteTmpDir(true);
return std::move(builtOutputs);
} catch (BuildError & e) {
return std::move(e);
throw BuildError(
!derivationType.isSandboxed() || diskFull ? BuildResult::TransientFailure : BuildResult::PermanentFailure,
msg);
}
}
void DerivationBuilderImpl::cleanupBuild()
{
deleteTmpDir(false);
/* Compute the FS closure of the outputs and register them as
being valid. */
auto builtOutputs = registerOutputs();
/* Delete unused redirected outputs (when doing hash rewriting). */
for (auto & i : redirectedOutputs)
deletePath(store.Store::toRealPath(i.second));
cleanupBuild(true);
return builtOutputs;
}
static void chmod_(const Path & path, mode_t mode)
@ -1757,7 +1799,6 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
}
store.optimisePath(actualPath, NoRepair); // FIXME: combine with scanForReferences()
miscMethods->markContentsGood(newInfo.path);
newInfo.deriver = drvPath;
newInfo.ultimate = true;
@ -1825,7 +1866,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
return builtOutputs;
}
void DerivationBuilderImpl::deleteTmpDir(bool force)
void DerivationBuilderImpl::cleanupBuild(bool force)
{
if (topTmpDir != "") {
/* As an extra precaution, even in the event of `deletePath` failing to

View file

@ -659,7 +659,7 @@ struct ChrootLinuxDerivationBuilder : ChrootDerivationBuilder, LinuxDerivationBu
throw SysError("setuid failed");
}
std::variant<BuildError, SingleDrvOutputs> unprepareBuild() override
SingleDrvOutputs unprepareBuild() override
{
sandboxMountNamespace = -1;
sandboxUserNamespace = -1;