Remove ostentatious interleaving of action output and progress messages.
I traced the use of FileOutErr to only be in SkyframeActionExecutor. The other event types generally wouldn't be expected to have stdout/stderr in any case.
Detailed changes:
* Change writeToStream to never show the progress bar, the one place it was asked to show the progress bar now does so explicitly.
* Move the display of any stdout/stderr to inside the switch cases that can have stdout/stderr in the first place, specifically before we redraw the progress bar.
* Don't flush the terminal before printing stdout/stderr, I don't see a reason to do that.
* Assert that no other events have stdout/stderr in the first place.
PiperOrigin-RevId: 343589378
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java
index 6256704..e7962a1 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/UiEventHandler.java
@@ -29,6 +29,7 @@
import com.google.devtools.build.lib.analysis.AnalysisPhaseCompleteEvent;
import com.google.devtools.build.lib.analysis.NoBuildEvent;
import com.google.devtools.build.lib.analysis.NoBuildRequestFinishedEvent;
+import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.buildeventstream.AnnounceBuildEventTransportsEvent;
import com.google.devtools.build.lib.buildeventstream.BuildEventTransport;
import com.google.devtools.build.lib.buildeventstream.BuildEventTransportClosedEvent;
@@ -302,11 +303,11 @@
stream.write(event.getMessageBytes());
stream.flush();
} else {
- writeToStream(
- stream,
- event.getKind(),
- event.getMessageBytes(),
- /*addBackProgressBar=*/ showProgress && cursorControl);
+ writeToStream(stream, event.getKind(), event.getMessageBytes());
+ if (showProgress && cursorControl) {
+ addProgressBar();
+ }
+ terminal.flush();
}
break;
case FATAL:
@@ -346,6 +347,14 @@
if (incompleteLine) {
crlf();
}
+ if (stderr != null) {
+ writeToStream(outErr.getErrorStream(), EventKind.STDERR, stderr);
+ outErr.getErrorStream().flush();
+ }
+ if (stdout != null) {
+ writeToStream(outErr.getOutputStream(), EventKind.STDOUT, stdout);
+ outErr.getOutputStream().flush();
+ }
if (showProgress && buildRunning && cursorControl) {
addProgressBar();
}
@@ -355,32 +364,19 @@
if (stateTracker.progressBarTimeDependent()) {
refresh();
}
- break;
+ // Fall through.
case START:
case FINISH:
case PASS:
case TIMEOUT:
case DEPCHECKER:
+ if (stdout != null || stderr != null) {
+ BugReport.sendBugReport(
+ new IllegalStateException(
+ "stdout/stderr should not be present for this event " + event));
+ }
break;
}
- if (stdout != null || stderr != null) {
- clearProgressBar();
- terminal.flush();
- if (stderr != null) {
- writeToStream(
- outErr.getErrorStream(), EventKind.STDERR, stderr, /*addBackProgressBar=*/ false);
- outErr.getErrorStream().flush();
- }
- if (stdout != null) {
- writeToStream(
- outErr.getOutputStream(), EventKind.STDOUT, stdout, /*addBackProgressBar=*/ false);
- outErr.getOutputStream().flush();
- }
- if (showProgress && cursorControl) {
- addProgressBar();
- }
- terminal.flush();
- }
}
}
@@ -456,8 +452,7 @@
handleInternal(event);
}
- private void writeToStream(
- OutputStream stream, EventKind eventKind, byte[] message, boolean addBackProgressBar)
+ private void writeToStream(OutputStream stream, EventKind eventKind, byte[] message)
throws IOException {
int eolIndex = Bytes.lastIndexOf(message, (byte) '\n');
ByteArrayOutputStream outLineBuffer =
@@ -478,10 +473,6 @@
stream.flush();
outLineBuffer.write(message, eolIndex + 1, message.length - eolIndex - 1);
- if (addBackProgressBar) {
- addProgressBar();
- terminal.flush();
- }
}
private void setEventKindColor(EventKind kind) throws IOException {
diff --git a/src/test/shell/integration/ui_test.sh b/src/test/shell/integration/ui_test.sh
index 7185411..55b5920 100755
--- a/src/test/shell/integration/ui_test.sh
+++ b/src/test/shell/integration/ui_test.sh
@@ -592,4 +592,44 @@
done
}
+function test_interleaved_errors_and_progress() {
+ # Background process necessary to interrupt Bazel doesn't go well on Windows.
+ [[ "$is_windows" == true ]] && return
+ mkdir -p foo
+ cat > foo/BUILD <<'EOF'
+genrule(name = 'sleep', outs = ['sleep.out'], cmd = 'sleep 10000')
+genrule(name = 'fail',
+ outs = ['fail.out'],
+ srcs = [':multiline.sh'],
+ cmd = '$(location :multiline.sh)'
+)
+EOF
+ cat > foo/multiline.sh <<'EOF'
+echo "This
+is
+a
+multiline error message
+before
+failure"
+false
+EOF
+ chmod +x foo/multiline.sh
+ bazel build -k //foo:all --curses=yes >& "$TEST_log" &
+ pid="$!"
+ while ! grep -q "multiline error message" "$TEST_log" ; do
+ sleep 1
+ done
+ while ! grep -q "Executing genrule //foo:sleep" "$TEST_log" ; do
+ sleep 1
+ done
+ kill -SIGINT "$pid"
+ wait "$pid" || exit_code="$?"
+ [[ "$exit_code" == 8 ]] || fail "Should have been interrupted: $exit_code"
+ tr -s <"$TEST_log" '\n' '@' |
+ grep -q 'Executing genrule //foo:fail failed:[^@]*@This@is@a@multiline error message@before@failure@\[2 / 3\] Executing genrule //foo:sleep;' \
+ || fail "Unified genrule error message not found"
+ # Make sure server is still usable.
+ bazel info server_pid >& "$TEST_log" || fail "Couldn't use server"
+}
+
run_suite "Integration tests for ${PRODUCT_NAME}'s UI"