Skip to content

Commit 1055c9f

Browse files
authored
Merge pull request #12630 from L-as/me/clean-up-drv-goal
Clean up derivation goals a bit
2 parents af4c587 + dc0bc7f commit 1055c9f

File tree

8 files changed

+236
-318
lines changed

8 files changed

+236
-318
lines changed

src/libstore/build/derivation-goal.cc

Lines changed: 80 additions & 158 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ Goal::Co DerivationGoal::tryToBuild()
649649
buildResult.startTime = time(0); // inexact
650650
started();
651651
co_await Suspend{};
652-
co_return buildDone();
652+
co_return hookDone();
653653
case rpPostpone:
654654
/* Not now; wait until at least one child finishes or
655655
the wake-up timeout expires. */
@@ -810,55 +810,6 @@ void replaceValidPath(const Path & storePath, const Path & tmpPath)
810810
}
811811

812812

813-
int DerivationGoal::getChildStatus()
814-
{
815-
#ifndef _WIN32 // TODO enable build hook on Windows
816-
return hook->pid.kill();
817-
#else
818-
return 0;
819-
#endif
820-
}
821-
822-
823-
void DerivationGoal::closeReadPipes()
824-
{
825-
#ifndef _WIN32 // TODO enable build hook on Windows
826-
hook->builderOut.readSide.close();
827-
hook->fromHook.readSide.close();
828-
#endif
829-
}
830-
831-
832-
void DerivationGoal::cleanupHookFinally()
833-
{
834-
}
835-
836-
837-
void DerivationGoal::cleanupPreChildKill()
838-
{
839-
}
840-
841-
842-
void DerivationGoal::cleanupPostChildKill()
843-
{
844-
}
845-
846-
847-
bool DerivationGoal::cleanupDecideWhetherDiskFull()
848-
{
849-
return false;
850-
}
851-
852-
853-
void DerivationGoal::cleanupPostOutputsRegisteredModeCheck()
854-
{
855-
}
856-
857-
858-
void DerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
859-
{
860-
}
861-
862813
void runPostBuildHook(
863814
Store & store,
864815
Logger & logger,
@@ -917,21 +868,53 @@ void runPostBuildHook(
917868
});
918869
}
919870

920-
Goal::Co DerivationGoal::buildDone()
871+
872+
void appendLogTailErrorMsg(
873+
Worker & worker,
874+
const StorePath & drvPath,
875+
const std::list<std::string> & logTail,
876+
std::string & msg)
921877
{
922-
trace("build done");
878+
if (!logger->isVerbose() && !logTail.empty()) {
879+
msg += fmt(";\nlast %d log lines:\n", logTail.size());
880+
for (auto & line : logTail) {
881+
msg += "> ";
882+
msg += line;
883+
msg += "\n";
884+
}
885+
auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand)
886+
? "nix log"
887+
: "nix-store -l";
888+
// The command is on a separate line for easy copying, such as with triple click.
889+
// This message will be indented elsewhere, so removing the indentation before the
890+
// command will not put it at the start of the line unfortunately.
891+
msg += fmt("For full logs, run:\n " ANSI_BOLD "%s %s" ANSI_NORMAL,
892+
nixLogCommand,
893+
worker.store.printStorePath(drvPath));
894+
}
895+
}
896+
923897

924-
Finally releaseBuildUser([&](){ this->cleanupHookFinally(); });
898+
Goal::Co DerivationGoal::hookDone()
899+
{
900+
#ifndef _WIN32
901+
assert(hook);
902+
#endif
925903

926-
cleanupPreChildKill();
904+
trace("hook build done");
927905

928906
/* Since we got an EOF on the logger pipe, the builder is presumed
929907
to have terminated. In fact, the builder could also have
930908
simply have closed its end of the pipe, so just to be sure,
931909
kill it. */
932-
int status = getChildStatus();
910+
int status =
911+
#ifndef _WIN32 // TODO enable build hook on Windows
912+
hook->pid.kill();
913+
#else
914+
0;
915+
#endif
933916

934-
debug("builder process for '%s' finished", worker.store.printStorePath(drvPath));
917+
debug("build hook for '%s' finished", worker.store.printStorePath(drvPath));
935918

936919
buildResult.timesBuilt++;
937920
buildResult.stopTime = time(0);
@@ -940,108 +923,59 @@ Goal::Co DerivationGoal::buildDone()
940923
worker.childTerminated(this);
941924

942925
/* Close the read side of the logger pipe. */
943-
closeReadPipes();
926+
#ifndef _WIN32 // TODO enable build hook on Windows
927+
hook->builderOut.readSide.close();
928+
hook->fromHook.readSide.close();
929+
#endif
944930

945931
/* Close the log file. */
946932
closeLogFile();
947933

948-
cleanupPostChildKill();
949-
950-
if (buildResult.cpuUser && buildResult.cpuSystem) {
951-
debug("builder for '%s' terminated with status %d, user CPU %.3fs, system CPU %.3fs",
952-
worker.store.printStorePath(drvPath),
953-
status,
954-
((double) buildResult.cpuUser->count()) / 1000000,
955-
((double) buildResult.cpuSystem->count()) / 1000000);
956-
}
957-
958-
bool diskFull = false;
959-
960-
try {
934+
/* Check the exit status. */
935+
if (!statusOk(status)) {
936+
auto msg = fmt("builder for '%s' %s",
937+
Magenta(worker.store.printStorePath(drvPath)),
938+
statusToString(status));
961939

962-
/* Check the exit status. */
963-
if (!statusOk(status)) {
940+
appendLogTailErrorMsg(worker, drvPath, logTail, msg);
964941

965-
diskFull |= cleanupDecideWhetherDiskFull();
966-
967-
auto msg = fmt("builder for '%s' %s",
968-
Magenta(worker.store.printStorePath(drvPath)),
969-
statusToString(status));
970-
971-
if (!logger->isVerbose() && !logTail.empty()) {
972-
msg += fmt(";\nlast %d log lines:\n", logTail.size());
973-
for (auto & line : logTail) {
974-
msg += "> ";
975-
msg += line;
976-
msg += "\n";
977-
}
978-
auto nixLogCommand = experimentalFeatureSettings.isEnabled(Xp::NixCommand)
979-
? "nix log"
980-
: "nix-store -l";
981-
// The command is on a separate line for easy copying, such as with triple click.
982-
// This message will be indented elsewhere, so removing the indentation before the
983-
// command will not put it at the start of the line unfortunately.
984-
msg += fmt("For full logs, run:\n " ANSI_BOLD "%s %s" ANSI_NORMAL,
985-
nixLogCommand,
986-
worker.store.printStorePath(drvPath));
987-
}
988-
989-
if (diskFull)
990-
msg += "\nnote: build failure may have been caused by lack of free disk space";
991-
992-
throw BuildError(msg);
993-
}
994-
995-
/* Compute the FS closure of the outputs and register them as
996-
being valid. */
997-
auto builtOutputs = registerOutputs();
998-
999-
StorePathSet outputPaths;
1000-
for (auto & [_, output] : builtOutputs)
1001-
outputPaths.insert(output.outPath);
1002-
runPostBuildHook(
1003-
worker.store,
1004-
*logger,
1005-
drvPath,
1006-
outputPaths
1007-
);
1008-
1009-
cleanupPostOutputsRegisteredModeNonCheck();
1010-
1011-
/* It is now safe to delete the lock files, since all future
1012-
lockers will see that the output paths are valid; they will
1013-
not create new lock files with the same names as the old
1014-
(unlinked) lock files. */
1015-
outputLocks.setDeletion(true);
1016942
outputLocks.unlock();
1017943

1018-
co_return done(BuildResult::Built, std::move(builtOutputs));
1019-
1020-
} catch (BuildError & e) {
1021-
outputLocks.unlock();
944+
/* TODO (once again) support fine-grained error codes, see issue #12641. */
1022945

1023-
BuildResult::Status st = BuildResult::MiscFailure;
946+
co_return done(BuildResult::MiscFailure, {}, BuildError(msg));
947+
}
1024948

1025-
#ifndef _WIN32 // TODO abstract over proc exit status
1026-
if (hook && WIFEXITED(status) && WEXITSTATUS(status) == 101)
1027-
st = BuildResult::TimedOut;
949+
/* Compute the FS closure of the outputs and register them as
950+
being valid. */
951+
auto builtOutputs =
952+
/* When using a build hook, the build hook can register the output
953+
as valid (by doing `nix-store --import'). If so we don't have
954+
to do anything here.
1028955
1029-
else if (hook && (!WIFEXITED(status) || WEXITSTATUS(status) != 100)) {
1030-
}
956+
We can only early return when the outputs are known a priori. For
957+
floating content-addressing derivations this isn't the case.
958+
*/
959+
assertPathValidity();
960+
961+
StorePathSet outputPaths;
962+
for (auto & [_, output] : builtOutputs)
963+
outputPaths.insert(output.outPath);
964+
runPostBuildHook(
965+
worker.store,
966+
*logger,
967+
drvPath,
968+
outputPaths
969+
);
1031970

1032-
else
1033-
#endif
1034-
{
1035-
assert(derivationType);
1036-
st =
1037-
dynamic_cast<NotDeterministic*>(&e) ? BuildResult::NotDeterministic :
1038-
statusOk(status) ? BuildResult::OutputRejected :
1039-
!derivationType->isSandboxed() || diskFull ? BuildResult::TransientFailure :
1040-
BuildResult::PermanentFailure;
1041-
}
971+
/* It is now safe to delete the lock files, since all future
972+
lockers will see that the output paths are valid; they will
973+
not create new lock files with the same names as the old
974+
(unlinked) lock files. */
975+
outputLocks.setDeletion(true);
976+
outputLocks.unlock();
1042977

1043-
co_return done(st, {}, std::move(e));
1044-
}
978+
co_return done(BuildResult::Built, std::move(builtOutputs));
1045979
}
1046980

1047981
Goal::Co DerivationGoal::resolvedFinished()
@@ -1093,7 +1027,7 @@ Goal::Co DerivationGoal::resolvedFinished()
10931027
: worker.store;
10941028
newRealisation.dependentRealisations = drvOutputReferences(worker.store, *drv, realisation.outPath, &drvStore);
10951029
}
1096-
signRealisation(newRealisation);
1030+
worker.store.signRealisation(newRealisation);
10971031
worker.store.registerDrvOutput(newRealisation);
10981032
}
10991033
outputPaths.insert(realisation.outPath);
@@ -1228,18 +1162,6 @@ HookReply DerivationGoal::tryBuildHook()
12281162
}
12291163

12301164

1231-
SingleDrvOutputs DerivationGoal::registerOutputs()
1232-
{
1233-
/* When using a build hook, the build hook can register the output
1234-
as valid (by doing `nix-store --import'). If so we don't have
1235-
to do anything here.
1236-
1237-
We can only early return when the outputs are known a priori. For
1238-
floating content-addressing derivations this isn't the case.
1239-
*/
1240-
return assertPathValidity();
1241-
}
1242-
12431165
Path DerivationGoal::openLogFile()
12441166
{
12451167
logSize = 0;

src/libstore/build/derivation-goal.hh

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ struct InitialOutput {
5555
std::optional<InitialOutputStatus> known;
5656
};
5757

58+
/** Used internally */
59+
void runPostBuildHook(
60+
Store & store,
61+
Logger & logger,
62+
const StorePath & drvPath,
63+
const StorePathSet & outputPaths);
64+
65+
/** Used internally */
66+
void appendLogTailErrorMsg(
67+
Worker & worker,
68+
const StorePath & drvPath,
69+
const std::list<std::string> & logTail,
70+
std::string & msg);
71+
5872
/**
5973
* A goal for building some or all of the outputs of a derivation.
6074
*/
@@ -232,7 +246,7 @@ struct DerivationGoal : public Goal
232246
Co gaveUpOnSubstitution();
233247
Co tryToBuild();
234248
virtual Co tryLocalBuild();
235-
Co buildDone();
249+
Co hookDone();
236250

237251
Co resolvedFinished();
238252

@@ -241,44 +255,16 @@ struct DerivationGoal : public Goal
241255
*/
242256
HookReply tryBuildHook();
243257

244-
virtual int getChildStatus();
245-
246-
/**
247-
* Check that the derivation outputs all exist and register them
248-
* as valid.
249-
*/
250-
virtual SingleDrvOutputs registerOutputs();
251-
252258
/**
253259
* Open a log file and a pipe to it.
254260
*/
255261
Path openLogFile();
256262

257-
/**
258-
* Sign the newly built realisation if the store allows it
259-
*/
260-
virtual void signRealisation(Realisation&) {}
261-
262263
/**
263264
* Close the log file.
264265
*/
265266
void closeLogFile();
266267

267-
/**
268-
* Close the read side of the logger pipe.
269-
*/
270-
virtual void closeReadPipes();
271-
272-
/**
273-
* Cleanup hooks for buildDone()
274-
*/
275-
virtual void cleanupHookFinally();
276-
virtual void cleanupPreChildKill();
277-
virtual void cleanupPostChildKill();
278-
virtual bool cleanupDecideWhetherDiskFull();
279-
virtual void cleanupPostOutputsRegisteredModeCheck();
280-
virtual void cleanupPostOutputsRegisteredModeNonCheck();
281-
282268
virtual bool isReadDesc(Descriptor fd);
283269

284270
/**

src/libstore/local-store.cc

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,19 +1585,6 @@ void LocalStore::addSignatures(const StorePath & storePath, const StringSet & si
15851585
}
15861586

15871587

1588-
void LocalStore::signRealisation(Realisation & realisation)
1589-
{
1590-
// FIXME: keep secret keys in memory.
1591-
1592-
auto secretKeyFiles = settings.secretKeyFiles;
1593-
1594-
for (auto & secretKeyFile : secretKeyFiles.get()) {
1595-
SecretKey secretKey(readFile(secretKeyFile));
1596-
LocalSigner signer(std::move(secretKey));
1597-
realisation.sign(signer);
1598-
}
1599-
}
1600-
16011588
void LocalStore::signPathInfo(ValidPathInfo & info)
16021589
{
16031590
// FIXME: keep secret keys in memory.

0 commit comments

Comments
 (0)