diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/execution_engine/traverser/traverser.hpp | 26 | ||||
-rw-r--r-- | src/buildtool/graph_traverser/graph_traverser.hpp | 22 |
2 files changed, 32 insertions, 16 deletions
diff --git a/src/buildtool/execution_engine/traverser/traverser.hpp b/src/buildtool/execution_engine/traverser/traverser.hpp index 930cf0fb..4d3fc7e9 100644 --- a/src/buildtool/execution_engine/traverser/traverser.hpp +++ b/src/buildtool/execution_engine/traverser/traverser.hpp @@ -1,6 +1,8 @@ #ifndef INCLUDED_SRC_BUILDTOOL_EXECUTION_ENGINE_TRAVERSER_TRAVERSER_HPP #define INCLUDED_SRC_BUILDTOOL_EXECUTION_ENGINE_TRAVERSER_TRAVERSER_HPP +#include <atomic> + #include "gsl-lite/gsl-lite.hpp" #include "src/buildtool/execution_engine/dag/dag.hpp" #include "src/buildtool/logging/logger.hpp" @@ -27,8 +29,14 @@ concept Runnable = requires(T const r, template <Runnable Executor> class Traverser { public: - Traverser(Executor const& r, DependencyGraph const& graph, std::size_t jobs) - : runner_{r}, graph_{graph}, tasker_{jobs} {} + Traverser(Executor const& r, + DependencyGraph const& graph, + std::size_t jobs, + gsl::not_null<std::atomic<bool>*> fail_flag) + : runner_{r}, + graph_{graph}, + failed_{std::move(fail_flag)}, + tasker_{jobs} {} Traverser() = delete; Traverser(Traverser const&) = delete; Traverser(Traverser&&) = delete; @@ -52,6 +60,7 @@ class Traverser { private: Executor const& runner_{}; DependencyGraph const& graph_; + gsl::not_null<std::atomic<bool>*> failed_; TaskSystem tasker_{}; // THIS SHOULD BE THE LAST MEMBER VARIABLE // Visits discover nodes and queue visits to their children nodes. @@ -77,7 +86,7 @@ class Traverser { void QueueVisit(NodeTypePtr node) noexcept { // in case the node was already discovered, there is no need to queue // the visit - if (node->TraversalState()->GetAndMarkDiscovered()) { + if (failed_->load() or node->TraversalState()->GetAndMarkDiscovered()) { return; } tasker_.QueueTask([this, node]() noexcept { Visit(node); }); @@ -89,7 +98,7 @@ class Traverser { // was successful template <typename NodeTypePtr> void QueueProcessing(NodeTypePtr node) noexcept { - if (not node->TraversalState()->IsRequired() or + if (failed_->load() or not node->TraversalState()->IsRequired() or node->TraversalState()->GetAndMarkQueuedToBeProcessed()) { return; } @@ -99,12 +108,16 @@ class Traverser { NotifyAvailable(node); } else { - Logger::Log(LogLevel::Error, "Build failed."); - std::exit(EXIT_FAILURE); + Abort(); } }; tasker_.QueueTask(process_node); } + + void Abort() noexcept { + failed_->store(true); + tasker_.Shutdown(); // skip execution of pending tasks + } }; template <Runnable Executor> @@ -116,6 +129,7 @@ auto Traverser<Executor>::Traverse( QueueVisit(artifact_node); } else { + Abort(); Logger::Log( LogLevel::Error, "artifact with id {} can not be found in dependency graph.", diff --git a/src/buildtool/graph_traverser/graph_traverser.hpp b/src/buildtool/graph_traverser/graph_traverser.hpp index fac93e27..c00fe61b 100644 --- a/src/buildtool/graph_traverser/graph_traverser.hpp +++ b/src/buildtool/graph_traverser/graph_traverser.hpp @@ -324,20 +324,21 @@ class GraphTraverser { Executor executor{&(*api_), RemoteExecutionConfig::PlatformProperties(), clargs_.build.timeout}; - bool result{}; + bool traversing{}; std::atomic<bool> done = false; + std::atomic<bool> failed = false; std::condition_variable cv{}; auto observer = std::thread([this, &done, &cv]() { reporter_(&done, &cv); }); { - Traverser t{executor, g, clargs_.jobs}; - result = + Traverser t{executor, g, clargs_.jobs, &failed}; + traversing = t.Traverse({std::begin(artifact_ids), std::end(artifact_ids)}); } done = true; cv.notify_all(); observer.join(); - return result; + return traversing and not failed; } [[nodiscard]] auto TraverseRebuild( @@ -350,18 +351,19 @@ class GraphTraverser { &(*api_cached), RemoteExecutionConfig::PlatformProperties(), clargs_.build.timeout}; - bool success{false}; + bool traversing{false}; + std::atomic<bool> failed{false}; { - Traverser t{executor, g, clargs_.jobs}; - success = + Traverser t{executor, g, clargs_.jobs, &failed}; + traversing = t.Traverse({std::begin(artifact_ids), std::end(artifact_ids)}); } - if (success and clargs_.rebuild->dump_flaky) { + if (traversing and not failed and clargs_.rebuild->dump_flaky) { std::ofstream file{*clargs_.rebuild->dump_flaky}; file << executor.DumpFlakyActions().dump(2); } - return success; + return traversing and not failed; } /// \brief Retrieves nodes corresponding to artifacts with ids in artifacts. @@ -463,7 +465,7 @@ class GraphTraverser { if (clargs_.rebuild ? not TraverseRebuild(*graph, artifact_ids) : not Traverse(*graph, artifact_ids)) { - Logger::Log(LogLevel::Error, "traversing graph failed."); + Logger::Log(LogLevel::Error, "Build failed."); return std::nullopt; } |