@@ -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-
862813void 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 (" ;\n last %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 (" ;\n last %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 += " \n note: 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
1047981Goal::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-
12431165Path DerivationGoal::openLogFile ()
12441166{
12451167 logSize = 0 ;
0 commit comments