From deea6b08efef98ae2ef03d516356ab3438d089c8 Mon Sep 17 00:00:00 2001 From: Klaus Aehlig Date: Mon, 16 Oct 2017 12:32:20 +0200 Subject: BuildEventStreamer: clear a pending BuildStarted event first If we receive an event indicating that the build is over, we first post that event and then clear up all pending event by stating that their prerequisite event was aborted (which we can safely assert, as we know we will not process any further events). Now, if a build is aborted (e.g., user interruption) before the build starting event is generated, the streamer can receive a build-finished event while still having an event (e.g., the raw command line) blocked on the build-starting event. So the canonical order of clearing the stream would send a build-finished event before the build-starting event, which can be confusing to consumers of the stream. Therefore, if have to generate an artificial aborted build-starting event, do so first (including clearing the events blocked on the build-starting event) and only afterwards post the build-finished event in the stream. Change-Id: Ib33f16f74b7bee7a963df94bbcad7a56db9f07e3 PiperOrigin-RevId: 172305114 --- .../build/lib/buildeventstream/AbortedEvent.java | 25 ++++++++++++++++++--- .../build/lib/runtime/BuildEventStreamer.java | 26 ++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) (limited to 'src/main/java/com/google') diff --git a/src/main/java/com/google/devtools/build/lib/buildeventstream/AbortedEvent.java b/src/main/java/com/google/devtools/build/lib/buildeventstream/AbortedEvent.java index 5816ecd3bd..0638c29552 100644 --- a/src/main/java/com/google/devtools/build/lib/buildeventstream/AbortedEvent.java +++ b/src/main/java/com/google/devtools/build/lib/buildeventstream/AbortedEvent.java @@ -16,7 +16,7 @@ package com.google.devtools.build.lib.buildeventstream; import com.google.common.collect.ImmutableList; import com.google.devtools.build.lib.cmdline.Label; - +import java.util.Collection; import javax.annotation.Nullable; /** A {@link BuildEvent} reporting an event not coming due to the build being aborted. */ @@ -26,14 +26,33 @@ public class AbortedEvent extends GenericBuildEvent { @Nullable private final Label label; public AbortedEvent( - BuildEventId id, BuildEventStreamProtos.Aborted.AbortReason reason, String description, + BuildEventId id, + Collection children, + BuildEventStreamProtos.Aborted.AbortReason reason, + String description, @Nullable Label label) { - super(id, ImmutableList.of()); + super(id, children); this.reason = reason; this.description = description; this.label = label; } + public AbortedEvent( + BuildEventId id, + BuildEventStreamProtos.Aborted.AbortReason reason, + String description, + @Nullable Label label) { + this(id, ImmutableList.of(), reason, description, label); + } + + public AbortedEvent( + BuildEventId id, + Collection children, + BuildEventStreamProtos.Aborted.AbortReason reason, + String description) { + this(id, children, reason, description, null); + } + public AbortedEvent( BuildEventId id, BuildEventStreamProtos.Aborted.AbortReason reason, String description) { this(id, reason, description, null); diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BuildEventStreamer.java b/src/main/java/com/google/devtools/build/lib/runtime/BuildEventStreamer.java index 3353d577e8..b393af0cb8 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/BuildEventStreamer.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/BuildEventStreamer.java @@ -254,6 +254,27 @@ public class BuildEventStreamer implements EventHandler { } } + /** + * If some events are blocked on the absence of a build_started event, generate such an event; + * moreover, make that artificial start event announce all events blocked on it, as well as the + * {@link BuildCompletingEvent} that caused the early end of the stream. + */ + private void clearMissingStartEvent(BuildEventId id) { + if (pendingEvents.containsKey(BuildEventId.buildStartedId())) { + ImmutableSet.Builder children = ImmutableSet.builder(); + children.add(ProgressEvent.INITIAL_PROGRESS_UPDATE); + children.add(id); + children.addAll( + pendingEvents + .get(BuildEventId.buildStartedId()) + .stream() + .map(BuildEvent::getEventId) + .collect(ImmutableSet.toImmutableSet())); + buildEvent( + new AbortedEvent(BuildEventId.buildStartedId(), children.build(), abortReason, "")); + } + } + /** Clear pending events by generating aborted events for all their requisits. */ private void clearPendingEvents() { while (!pendingEvents.isEmpty()) { @@ -404,6 +425,11 @@ public class BuildEventStreamer implements EventHandler { } } + if (event instanceof BuildCompletingEvent + && !event.getEventId().equals(BuildEventId.buildStartedId())) { + clearMissingStartEvent(event.getEventId()); + } + post(event); // Reconsider all events blocked by the event just posted. -- cgit v1.2.3