From 170e57d06326c8773cf3cfd3f3d73fda2e9c8cc5 Mon Sep 17 00:00:00 2001 From: Chi Wang Date: Thu, 22 Jul 2021 04:58:40 -0700 Subject: [PATCH] Remote: Fix a race when reporting action progresses. Fixes https://github.com/bazelbuild/bazel/issues/13713. I will create checkpick request for 4.2.0 once merged into main branch. Closes #13719. PiperOrigin-RevId: 386213448 --- .../build/lib/runtime/UiStateTracker.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/runtime/UiStateTracker.java b/src/main/java/com/google/devtools/build/lib/runtime/UiStateTracker.java index c709eb36316840..eef7ea5c64ae7c 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/UiStateTracker.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/UiStateTracker.java @@ -62,12 +62,14 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.PriorityQueue; import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import javax.annotation.Nullable; +import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.ThreadSafe; /** Tracks state for the UI. */ @@ -228,6 +230,7 @@ private ProgressState(String id, long nanoStartTime) { } } + @GuardedBy("this") private final LinkedHashMap runningProgresses = new LinkedHashMap<>(); /** Starts tracking the state of an action. */ @@ -333,6 +336,13 @@ synchronized void onProgressEvent(ActionProgressEvent event, long nanoChangeTime state.latestEvent = event; } + synchronized Optional firstProgress() { + if (runningProgresses.isEmpty()) { + return Optional.empty(); + } + return Optional.of(runningProgresses.entrySet().iterator().next().getValue()); + } + /** Generates a human-readable description of this action's state. */ synchronized String describe() { if (runningStrategiesBitmap != 0) { @@ -705,12 +715,12 @@ private String describeTestGroup( } private String describeActionProgress(ActionState action, int desiredWidth) { - if (action.runningProgresses.isEmpty()) { + Optional stateOpt = action.firstProgress(); + if (!stateOpt.isPresent()) { return ""; } - ActionState.ProgressState state = - action.runningProgresses.entrySet().iterator().next().getValue(); + ActionState.ProgressState state = stateOpt.get(); ActionProgressEvent event = state.latestEvent; String message = event.progress(); if (message.isEmpty()) {