Skip to content

Commit 5b95d91

Browse files
larsrc-googlecopybara-github
authored andcommitted
Check the result of Future.cancel() when cancelling the other branch of dynamic execution.
Under --experimental_local_lockfree_output, the local branch may succeed and set the future before cancelling the remote branch. If the remote branch succeeded after that but before the local listener got going, it would falsely think the local was cancelled, which would occasionally lead to strange errors. RELNOTES: None. PiperOrigin-RevId: 373347494
1 parent ba4435c commit 5b95d91

2 files changed

Lines changed: 15 additions & 1 deletion

File tree

src/main/java/com/google/devtools/build/lib/actions/DynamicStrategyRegistry.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ enum DynamicMode {
3434
public String toString() {
3535
return name;
3636
}
37+
38+
public DynamicMode other() {
39+
return this == REMOTE ? LOCAL : REMOTE;
40+
}
3741
}
3842

3943
/**

src/main/java/com/google/devtools/build/lib/dynamic/DynamicSpawnStrategy.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,17 @@ private static void stopBranch(
173173
spawn.getMnemonic(), strategyThatCancelled.get())));
174174
}
175175

176-
branchToCancel.cancel(true);
176+
if (!branchToCancel.cancel(true)) {
177+
// This can happen if the other branch is local under local_lockfree and has returned
178+
// its result but not yet cancelled this branch, or if the other branch was already
179+
// cancelled for other reasons.
180+
if (!branchToCancel.isCancelled()) {
181+
throw new DynamicInterruptedException(
182+
String.format(
183+
"Execution of %s strategy stopped because %s strategy could not be cancelled",
184+
cancellingStrategy, cancellingStrategy.other()));
185+
}
186+
}
177187
branchDone.acquire();
178188
} else {
179189
throw new DynamicInterruptedException(

0 commit comments

Comments
 (0)