use of com.google.devtools.build.lib.actions.BuildFailedException in project bazel by bazelbuild.
the class SkyframeBuilder method buildArtifacts.
@Override
public void buildArtifacts(Reporter reporter, Set<Artifact> artifacts, Set<ConfiguredTarget> parallelTests, Set<ConfiguredTarget> exclusiveTests, Collection<ConfiguredTarget> targetsToBuild, Collection<AspectValue> aspects, Executor executor, Set<ConfiguredTarget> builtTargets, boolean explain, @Nullable Range<Long> lastExecutionTimeRange, TopLevelArtifactContext topLevelArtifactContext) throws BuildFailedException, AbruptExitException, TestExecException, InterruptedException {
skyframeExecutor.prepareExecution(modifiedOutputFiles, lastExecutionTimeRange);
skyframeExecutor.setFileCache(fileCache);
// Note that executionProgressReceiver accesses builtTargets concurrently (after wrapping in a
// synchronized collection), so unsynchronized access to this variable is unsafe while it runs.
ExecutionProgressReceiver executionProgressReceiver = new ExecutionProgressReceiver(Preconditions.checkNotNull(builtTargets), countTestActions(exclusiveTests), ImmutableSet.<ConfiguredTarget>builder().addAll(parallelTests).addAll(exclusiveTests).build(), topLevelArtifactContext, skyframeExecutor.getEventBus());
skyframeExecutor.getEventBus().post(new ExecutionProgressReceiverAvailableEvent(executionProgressReceiver));
List<ExitCode> exitCodes = new LinkedList<>();
EvaluationResult<?> result;
ActionExecutionStatusReporter statusReporter = ActionExecutionStatusReporter.create(reporter, executor, skyframeExecutor.getEventBus());
AtomicBoolean isBuildingExclusiveArtifacts = new AtomicBoolean(false);
ActionExecutionInactivityWatchdog watchdog = new ActionExecutionInactivityWatchdog(executionProgressReceiver.createInactivityMonitor(statusReporter), executionProgressReceiver.createInactivityReporter(statusReporter, isBuildingExclusiveArtifacts), progressReportInterval);
skyframeExecutor.setActionExecutionProgressReportingObjects(executionProgressReceiver, executionProgressReceiver, statusReporter);
watchdog.start();
try {
result = skyframeExecutor.buildArtifacts(reporter, executor, artifacts, targetsToBuild, aspects, parallelTests, /*exclusiveTesting=*/
false, keepGoing, explain, finalizeActionsToOutputService, numJobs, actionCacheChecker, executionProgressReceiver, topLevelArtifactContext);
// progressReceiver is finished, so unsynchronized access to builtTargets is now safe.
Optional<ExitCode> exitCode = processResult(reporter, result, keepGoing, skyframeExecutor);
Preconditions.checkState(exitCode != null || result.keyNames().size() == (artifacts.size() + targetsToBuild.size() + aspects.size() + parallelTests.size()), "Build reported as successful but not all artifacts and targets built: %s, %s", result, artifacts);
if (exitCode != null) {
exitCodes.add(exitCode.orNull());
}
// Run exclusive tests: either tagged as "exclusive" or is run in an invocation with
// --test_output=streamed.
isBuildingExclusiveArtifacts.set(true);
for (ConfiguredTarget exclusiveTest : exclusiveTests) {
// Since only one artifact is being built at a time, we don't worry about an artifact being
// built and then the build being interrupted.
result = skyframeExecutor.buildArtifacts(reporter, executor, ImmutableSet.<Artifact>of(), targetsToBuild, aspects, ImmutableSet.of(exclusiveTest), /*exclusiveTesting=*/
true, keepGoing, explain, finalizeActionsToOutputService, numJobs, actionCacheChecker, null, topLevelArtifactContext);
exitCode = processResult(reporter, result, keepGoing, skyframeExecutor);
Preconditions.checkState(exitCode != null || !result.keyNames().isEmpty(), "Build reported as successful but test %s not executed: %s", exclusiveTest, result);
if (exitCode != null) {
exitCodes.add(exitCode.orNull());
}
}
} finally {
watchdog.stop();
skyframeExecutor.setActionExecutionProgressReportingObjects(null, null, null);
statusReporter.unregisterFromEventBus();
}
if (!exitCodes.isEmpty()) {
if (keepGoing) {
// Use the exit code with the highest priority.
throw new BuildFailedException(null, Collections.max(exitCodes, ExitCodeComparator.INSTANCE));
} else {
throw new BuildFailedException();
}
}
}
use of com.google.devtools.build.lib.actions.BuildFailedException in project bazel by bazelbuild.
the class ParallelBuilderTest method testFailureRecovery.
/**
* Test that we can recover properly after a failed build.
*/
@Test
public void testFailureRecovery() throws Exception {
// [action] -> foo
Artifact foo = createDerivedArtifact("foo");
Callable<Void> makeFoo = new Callable<Void>() {
@Override
public Void call() throws IOException {
throw new IOException("building 'foo' is supposed to fail");
}
};
registerAction(new TestAction(makeFoo, Artifact.NO_ARTIFACTS, ImmutableList.of(foo)));
// [action] -> bar
Artifact bar = createDerivedArtifact("bar");
registerAction(new TestAction(TestAction.NO_EFFECT, emptySet, ImmutableList.of(bar)));
// Don't fail fast when we encounter the error
reporter.removeHandler(failFastHandler);
// test that building 'foo' fails
try {
buildArtifacts(foo);
fail("building 'foo' was supposed to fail!");
} catch (BuildFailedException e) {
if (!e.getMessage().contains("building 'foo' is supposed to fail")) {
throw e;
}
// Make sure the reporter reported the error message.
assertContainsEvent("building 'foo' is supposed to fail");
}
// test that a subsequent build of 'bar' succeeds
buildArtifacts(bar);
}
use of com.google.devtools.build.lib.actions.BuildFailedException in project bazel by bazelbuild.
the class ParallelBuilderTest method testCyclicActionGraphWithTail.
@Test
public void testCyclicActionGraphWithTail() throws Exception {
// bar -> [action] -> foo
// baz -> [action] -> bar
// bat, foo -> [action] -> baz
Artifact foo = createDerivedArtifact("foo");
Artifact bar = createDerivedArtifact("bar");
Artifact baz = createDerivedArtifact("baz");
Artifact bat = createDerivedArtifact("bat");
try {
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(foo)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(baz), asSet(bar)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bat, foo), asSet(baz)));
registerAction(new TestAction(TestAction.NO_EFFECT, ImmutableSet.<Artifact>of(), asSet(bat)));
buildArtifacts(foo);
fail("Builder failed to detect cyclic action graph");
} catch (BuildFailedException e) {
assertEquals(e.getMessage(), CYCLE_MSG);
}
}
use of com.google.devtools.build.lib.actions.BuildFailedException in project bazel by bazelbuild.
the class ParallelBuilderTest method assertNoNewJobsAreRunAfterFirstFailure.
// Regression test for bug #735765, "ParallelBuilder still issues new jobs
// after one has failed, without --keep-going." The incorrect behaviour is
// that, when the first job fails, while no new jobs are added to the queue
// of runnable jobs, the queue may have lots of work in it, and the
// ParallelBuilder always completes these jobs before it returns. The
// correct behaviour is to discard all the jobs in the queue after the first
// one fails.
public void assertNoNewJobsAreRunAfterFirstFailure(final boolean catastrophe, boolean keepGoing) throws Exception {
// Strategy: Limit parallelism to 3. Enqueue 10 runnable tasks that run
// for an appreciable period (say 100ms). Ensure that at most 3 of those
// tasks completed. This proves that all runnable tasks were dropped from
// the queue after the first batch (which included errors) was finished.
// It should be pretty robust even in the face of timing variations.
final AtomicInteger completedTasks = new AtomicInteger(0);
int numJobs = 50;
Artifact[] artifacts = new Artifact[numJobs];
for (int ii = 0; ii < numJobs; ++ii) {
Artifact out = createDerivedArtifact(ii + ".out");
List<Artifact> inputs = (catastrophe && ii > 10) ? ImmutableList.of(artifacts[0]) : Artifact.NO_ARTIFACTS;
final int iCopy = ii;
registerAction(new TestAction(new Callable<Void>() {
@Override
public Void call() throws Exception {
// 100ms
Thread.sleep(100);
completedTasks.getAndIncrement();
throw new IOException("task failed");
}
}, inputs, ImmutableList.of(out)) {
@Override
public void execute(ActionExecutionContext actionExecutionContext) throws ActionExecutionException {
if (catastrophe && iCopy == 0) {
try {
// 300ms
Thread.sleep(300);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
completedTasks.getAndIncrement();
throw new ActionExecutionException("This is a catastrophe", this, true);
}
super.execute(actionExecutionContext);
}
});
artifacts[ii] = out;
}
// Don't fail fast when we encounter the error
reporter.removeHandler(failFastHandler);
try {
buildArtifacts(createBuilder(3, keepGoing), artifacts);
fail();
} catch (BuildFailedException e) {
assertContainsEvent("task failed");
}
if (completedTasks.get() >= numJobs) {
fail("Expected early termination due to failed task, but all tasks ran to completion.");
}
}
use of com.google.devtools.build.lib.actions.BuildFailedException in project bazel by bazelbuild.
the class ParallelBuilderTest method testCycleInActionGraphBelowTwoActions.
@Test
public void testCycleInActionGraphBelowTwoActions() throws Exception {
// bar -> [action] -> foo1
// bar -> [action] -> foo2
// baz -> [action] -> bar
// bar -> [action] -> baz
Artifact foo1 = createDerivedArtifact("foo1");
Artifact foo2 = createDerivedArtifact("foo2");
Artifact bar = createDerivedArtifact("bar");
Artifact baz = createDerivedArtifact("baz");
try {
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(foo1)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(foo2)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(baz), asSet(bar)));
registerAction(new TestAction(TestAction.NO_EFFECT, asSet(bar), asSet(baz)));
buildArtifacts(foo1, foo2);
fail("Builder failed to detect cyclic action graph");
} catch (BuildFailedException e) {
assertEquals(e.getMessage(), CYCLE_MSG);
}
}
Aggregations