Skip to content

Commit 6802831

Browse files
aehligkatre
authored andcommitted
experimental UI: move stopUpdateThread() out of synchronized, again
The experimental UI uses a thread to regularly update itself to reflect time-based changes. As that that thread has to call synchronized methods any waiting for it to finish has to happen outside any synchronized block. Unfortunately, 9e0308e accidentally moved the stopUpdateThread() in buildComplete() into the synchronized block, thus giving an opportunity for deadlocks. Move it out again. Also, as the accounting for pending transports now happens in synchronized methods in the state tracker, the buildEventTransportClosed() method does not have to be synchronized any more---thus eliminating the second deadlock opportunity. Change-Id: Icacb2ee70f4bedde1c1aac2bcfefc6fabf42fdd3 PiperOrigin-RevId: 158537844
1 parent b6ea82a commit 6802831

1 file changed

Lines changed: 12 additions & 3 deletions

File tree

src/main/java/com/google/devtools/build/lib/runtime/ExperimentalEventHandler.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ public void progressReceiverAvailable(ExecutionProgressReceiverAvailableEvent ev
446446
public void buildComplete(BuildCompleteEvent event) {
447447
// The final progress bar will flow into the scroll-back buffer, to if treat
448448
// it as an event and add a timestamp, if events are supposed to have a timestmap.
449+
boolean done = false;
449450
synchronized (this) {
450451
stateTracker.buildComplete(event);
451452
ignoreRefreshLimitOnce();
@@ -455,10 +456,13 @@ public void buildComplete(BuildCompleteEvent event) {
455456
// upload happening.
456457
if (stateTracker.pendingTransports() == 0) {
457458
buildComplete = true;
458-
stopUpdateThread();
459-
flushStdOutStdErrBuffers();
459+
done = true;
460460
}
461461
}
462+
if (done) {
463+
stopUpdateThread();
464+
flushStdOutStdErrBuffers();
465+
}
462466
}
463467

464468
@Subscribe
@@ -574,7 +578,7 @@ public synchronized void buildEventTransportsAnnounced(AnnounceBuildEventTranspo
574578
}
575579

576580
@Subscribe
577-
public synchronized void buildEventTransportClosed(BuildEventTransportClosedEvent event) {
581+
public void buildEventTransportClosed(BuildEventTransportClosedEvent event) {
578582
stateTracker.buildEventTransportClosed(event);
579583
if (debugAllEvents) {
580584
this.handle(Event.info(null, "Transport " + event.transport().name() + " closed"));
@@ -721,6 +725,11 @@ public void run() {
721725
}
722726
}
723727

728+
/**
729+
* Stop the update thread and wait for it to terminate. As the update thread, which is a separate
730+
* thread, might have to call a synchronized method between being interrupted and terminating, DO
731+
* NOT CALL from a SYNCHRONIZED block, as this will give the opportunity for dead locks.
732+
*/
724733
private void stopUpdateThread() {
725734
Thread threadToWaitFor = null;
726735
synchronized (this) {

0 commit comments

Comments
 (0)