ExperimentalEventHandler: add a shutdown flag
We've observed hangs of Bazel on shutdown with thread stacks indicating
that the cli-update-thread does not exit properly. We don't know why
this is happening, and have no easy way to reproduce.
My best guess is that the interrupt is swallowed somewhere, although I
was unable to pinpoint a specific place where that could happen. As a
defensive mechanism, this change adds a boolean flag that signals to the
CLI thread to shutdown in case the interrupt signal gets lost. This also
helps with a potential race between startUpdateThread and
stopUpdateThread.
Possible fix for #8432.
PiperOrigin-RevId: 249612495
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
index e8753fa..f990bf0 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java
@@ -112,6 +112,7 @@
private boolean buildRunning;
// Number of open build even protocol transports.
private boolean progressBarNeedsRefresh;
+ private volatile boolean shutdown;
private final AtomicReference<Thread> updateThread;
private byte[] stdoutBuffer;
private byte[] stderrBuffer;
@@ -990,7 +991,7 @@
new Thread(
() -> {
try {
- while (true) {
+ while (!shutdown) {
Thread.sleep(minimalUpdateInterval);
if (lastRefreshMillis < mustRefreshAfterMillis
&& mustRefreshAfterMillis < clock.currentTimeMillis()) {
@@ -1015,6 +1016,7 @@
* NOT CALL from a SYNCHRONIZED block, as this will give the opportunity for dead locks.
*/
private void stopUpdateThread() {
+ shutdown = true;
Thread threadToWaitFor = updateThread.getAndSet(null);
if (threadToWaitFor != null) {
threadToWaitFor.interrupt();