Skip to content

Commit

Permalink
Adding debugging information for case when two branches apparently ca…
Browse files Browse the repository at this point in the history
…ncel each other.

RELNOTES: None.
PiperOrigin-RevId: 352596000
  • Loading branch information
larsrc-google authored and Copybara-Service committed Jan 19, 2021
1 parent fbbc4f6 commit 039461c
Showing 1 changed file with 23 additions and 17 deletions.
Expand Up @@ -230,37 +230,43 @@ private static ImmutableList<SpawnResult> waitBranch(Future<ImmutableList<SpawnR
* <p>This guarantees that the two branches are stopped both on successful termination and on an
* exception.
*
* @param branch1 the future running one side of the spawn (e.g. local). This future must cancel
* {@code branch2} at some point during its successful execution to guarantee termination. If
* we encounter an execution error, or if we are interrupted, then we handle such cancellation
* here.
* @param branch2 the future running the other side of the spawn (e.g. remote). Same restrictions
* apply as in {@code branch1}, but in the symmetric direction.
* @param localBranch the future running the local side of the spawn. This future must cancel
* {@code remoteBranch} at some point during its successful execution to guarantee
* termination. If we encounter an execution error, or if we are interrupted, then we handle
* such cancellation here.
* @param remoteBranch the future running the remote side of the spawn. Same restrictions apply as
* in {@code localBranch}, but in the symmetric direction.
* @return the result of the branch that terminates first
* @throws ExecException the execution error of the spawn that terminated first
* @throws InterruptedException if we get interrupted while waiting for completion
*/
private static ImmutableList<SpawnResult> waitBranches(
Future<ImmutableList<SpawnResult>> branch1, Future<ImmutableList<SpawnResult>> branch2)
Future<ImmutableList<SpawnResult>> localBranch,
Future<ImmutableList<SpawnResult>> remoteBranch)
throws ExecException, InterruptedException {
ImmutableList<SpawnResult> result1;
ImmutableList<SpawnResult> localResult;
try {
result1 = waitBranch(branch1);
localResult = waitBranch(localBranch);
} catch (ExecException | InterruptedException | RuntimeException e) {
branch2.cancel(true);
remoteBranch.cancel(true);
throw e;
}

ImmutableList<SpawnResult> result2 = waitBranch(branch2);
ImmutableList<SpawnResult> remoteResult = waitBranch(remoteBranch);

if (result2 != null && result1 != null) {
if (remoteResult != null && localResult != null) {
throw new AssertionError("One branch did not cancel the other one");
} else if (result2 != null) {
return result2;
} else if (result1 != null) {
return result1;
} else if (remoteResult != null) {
return remoteResult;
} else if (localResult != null) {
return localResult;
} else {
throw new AssertionError("No branch completed, which might mean they cancelled each other");
throw new AssertionError(
"Neither branch completed. Local was "
+ (localBranch.isCancelled() ? "" : "not ")
+ "cancelled and remote was "
+ (remoteBranch.isCancelled() ? "" : "not ")
+ "cancelled");
}
}

Expand Down

0 comments on commit 039461c

Please sign in to comment.