From ca68979174da416f0c3d11beaa19d3965a4654a0 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Fri, 24 Jan 2025 14:18:25 +0100 Subject: [PATCH] libutil: add interruptible promise wrapping the worker already wants to make a promise explicitly control-C-able, and some other things in the future will want this as well. we do not yet have the option to use the signal interfaces kj offers, but if we can manage to remove all uses of the old-style notifiers we might get there. until then we can at least wrap the old interfaces to be a bit nicer to use, and eventually easier to replace with kj-provided code. Change-Id: I079fdfe7720485820a9862c3615335d4e1df13e7 --- lix/libstore/build/worker.cc | 9 +-------- lix/libutil/signals.hh | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lix/libstore/build/worker.cc b/lix/libstore/build/worker.cc index ae23463b3..2c1ac9c0c 100644 --- a/lix/libstore/build/worker.cc +++ b/lix/libstore/build/worker.cc @@ -236,14 +236,7 @@ try { running = true; Finally const _stop([&] { running = false; }); - auto onInterrupt = kj::newPromiseAndCrossThreadFulfiller>(); - auto interruptCallback = createInterruptCallback([&] { - onInterrupt.fulfiller->fulfill(result::failure(std::make_exception_ptr(makeInterrupted()))); - }); - - auto promise = runImpl(std::move(topGoals)) - .exclusiveJoin(updateStatistics()) - .exclusiveJoin(std::move(onInterrupt.promise)); + auto promise = makeInterruptible(runImpl(std::move(topGoals))).exclusiveJoin(updateStatistics()); // TODO GC interface? if (auto localStore = dynamic_cast(&store); localStore && settings.minFree != 0u) { diff --git a/lix/libutil/signals.hh b/lix/libutil/signals.hh index 75a5b3caf..12d8ced62 100644 --- a/lix/libutil/signals.hh +++ b/lix/libutil/signals.hh @@ -20,7 +20,10 @@ #include "lix/libutil/error.hh" +#include "lix/libutil/result.hh" +#include +#include #include #include #include @@ -107,6 +110,17 @@ struct InterruptCallback std::unique_ptr createInterruptCallback( std::function callback); +template +kj::Promise> makeInterruptible(kj::Promise> p) +{ + auto onInterrupt = kj::newPromiseAndCrossThreadFulfiller>(); + auto interruptCallback = createInterruptCallback([fulfiller{onInterrupt.fulfiller.get()}] { + fulfiller->fulfill(result::failure(std::make_exception_ptr(makeInterrupted()))); + }); + return p.attach(std::move(onInterrupt.fulfiller), std::move(interruptCallback)) + .exclusiveJoin(std::move(onInterrupt.promise)); +} + void triggerInterrupt(); /**