aboutsummaryrefslogtreecommitdiff
path: root/src/libstore/build/substitution-goal.cc
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-09-01 01:37:10 +0200
committereldritch horrors <pennae@lix.systems>2024-09-08 01:57:48 +0000
commitf2a49032a698bd96b37e8df8f02ec403fd0bed0f (patch)
tree746a9965d12326e6ef68b527b4c868758b79abf8 /src/libstore/build/substitution-goal.cc
parent92eccfbd68f80e4a5d87556d43927d6dbaabae26 (diff)
libstore: turn Worker in a kj event loop user
using a proper event loop basis we no longer have to worry about most of the intricacies of poll(), or platform-dependent replacements for it. we may even be able to use the event loop and its promise system for all of our scheduling in the future. we don't do any real async processing yet, this is just preparation to separate the first such change from the huge api design difference with the async framework we chose (kj from capnp): kj::Promise, unlike std::future, doesn't return exceptions unmangled. it instead wraps any non-kj exception into a kj exception, erasing all type information and preserving mostly the what() string in the process. this makes sense in the capnp rpc use case where unrestricted exception types can't be transferred, and since it moves error handling styles closer to a world we'd actually like there's no harm in doing it only here for now Change-Id: I20f888de74d525fb2db36ca30ebba4bcfe9cc838
Diffstat (limited to 'src/libstore/build/substitution-goal.cc')
-rw-r--r--src/libstore/build/substitution-goal.cc50
1 files changed, 30 insertions, 20 deletions
diff --git a/src/libstore/build/substitution-goal.cc b/src/libstore/build/substitution-goal.cc
index 33715ea6b..bd0ffcb9b 100644
--- a/src/libstore/build/substitution-goal.cc
+++ b/src/libstore/build/substitution-goal.cc
@@ -45,21 +45,21 @@ Goal::Finished PathSubstitutionGoal::done(
}
-Goal::WorkResult PathSubstitutionGoal::work(bool inBuildSlot)
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::work(bool inBuildSlot) noexcept
{
return (this->*state)(inBuildSlot);
}
-Goal::WorkResult PathSubstitutionGoal::init(bool inBuildSlot)
-{
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::init(bool inBuildSlot) noexcept
+try {
trace("init");
worker.store.addTempRoot(storePath);
/* If the path already exists we're done. */
if (!repair && worker.store.isValidPath(storePath)) {
- return done(ecSuccess, BuildResult::AlreadyValid);
+ return {done(ecSuccess, BuildResult::AlreadyValid)};
}
if (settings.readOnlyMode)
@@ -68,11 +68,13 @@ Goal::WorkResult PathSubstitutionGoal::init(bool inBuildSlot)
subs = settings.useSubstitutes ? getDefaultSubstituters() : std::list<ref<Store>>();
return tryNext(inBuildSlot);
+} catch (...) {
+ return {std::current_exception()};
}
-Goal::WorkResult PathSubstitutionGoal::tryNext(bool inBuildSlot)
-{
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::tryNext(bool inBuildSlot) noexcept
+try {
trace("trying next substituter");
cleanup();
@@ -87,10 +89,10 @@ Goal::WorkResult PathSubstitutionGoal::tryNext(bool inBuildSlot)
/* Hack: don't indicate failure if there were no substituters.
In that case the calling derivation should just do a
build. */
- return done(
+ return {done(
substituterFailed ? ecFailed : ecNoSubstituters,
BuildResult::NoSubstituters,
- fmt("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath)));
+ fmt("path '%s' is required, but there is no substituter that can build it", worker.store.printStorePath(storePath)))};
}
sub = subs.front();
@@ -167,20 +169,22 @@ Goal::WorkResult PathSubstitutionGoal::tryNext(bool inBuildSlot)
return referencesValid(inBuildSlot);
} else {
state = &PathSubstitutionGoal::referencesValid;
- return result;
+ return {std::move(result)};
}
+} catch (...) {
+ return {std::current_exception()};
}
-Goal::WorkResult PathSubstitutionGoal::referencesValid(bool inBuildSlot)
-{
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::referencesValid(bool inBuildSlot) noexcept
+try {
trace("all references realised");
if (nrFailed > 0) {
- return done(
+ return {done(
nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed,
BuildResult::DependencyFailed,
- fmt("some references of path '%s' could not be realised", worker.store.printStorePath(storePath)));
+ fmt("some references of path '%s' could not be realised", worker.store.printStorePath(storePath)))};
}
for (auto & i : info->references)
@@ -189,15 +193,17 @@ Goal::WorkResult PathSubstitutionGoal::referencesValid(bool inBuildSlot)
state = &PathSubstitutionGoal::tryToRun;
return tryToRun(inBuildSlot);
+} catch (...) {
+ return {std::current_exception()};
}
-Goal::WorkResult PathSubstitutionGoal::tryToRun(bool inBuildSlot)
-{
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::tryToRun(bool inBuildSlot) noexcept
+try {
trace("trying to run");
if (!inBuildSlot) {
- return WaitForSlot{};
+ return {WaitForSlot{}};
}
maintainRunningSubstitutions = worker.runningSubstitutions.addTemporarily(1);
@@ -228,12 +234,14 @@ Goal::WorkResult PathSubstitutionGoal::tryToRun(bool inBuildSlot)
});
state = &PathSubstitutionGoal::finished;
- return WaitForWorld{{outPipe.readSide.get()}, true};
+ return {WaitForWorld{{outPipe.readSide.get()}, true}};
+} catch (...) {
+ return {std::current_exception()};
}
-Goal::WorkResult PathSubstitutionGoal::finished(bool inBuildSlot)
-{
+kj::Promise<Result<Goal::WorkResult>> PathSubstitutionGoal::finished(bool inBuildSlot) noexcept
+try {
trace("substitute finished");
worker.childTerminated(this);
@@ -274,7 +282,9 @@ Goal::WorkResult PathSubstitutionGoal::finished(bool inBuildSlot)
worker.doneNarSize += maintainExpectedNar.delta();
maintainExpectedNar.reset();
- return done(ecSuccess, BuildResult::Substituted);
+ return {done(ecSuccess, BuildResult::Substituted)};
+} catch (...) {
+ return {std::current_exception()};
}