diff --git a/xds/src/main/java/io/grpc/xds/ControlPlaneClient.java b/xds/src/main/java/io/grpc/xds/ControlPlaneClient.java index 5f013bfd3b..3ce2815d9d 100644 --- a/xds/src/main/java/io/grpc/xds/ControlPlaneClient.java +++ b/xds/src/main/java/io/grpc/xds/ControlPlaneClient.java @@ -392,7 +392,9 @@ final class ControlPlaneClient { // has never been initialized. retryBackoffPolicy = backoffPolicyProvider.get(); } - // Need this here to avoid tsan race condition in XdsClientImplTestBase.sendToNonexistentHost + // FakeClock in tests isn't thread-safe. Schedule the retry timer before notifying callbacks + // to avoid TSAN races, since tests may wait until callbacks are called but then would run + // concurrently with the stopwatch and schedule. long elapsed = stopwatch.elapsed(TimeUnit.NANOSECONDS); long delayNanos = Math.max(0, retryBackoffPolicy.nextBackoffNanos() - elapsed); rpcRetryTimer = syncContext.schedule( diff --git a/xds/src/test/java/io/grpc/xds/XdsClientImplTestBase.java b/xds/src/test/java/io/grpc/xds/XdsClientImplTestBase.java index 9f1be942ea..fe502a2303 100644 --- a/xds/src/test/java/io/grpc/xds/XdsClientImplTestBase.java +++ b/xds/src/test/java/io/grpc/xds/XdsClientImplTestBase.java @@ -3726,9 +3726,12 @@ public abstract class XdsClientImplTestBase { } @Test - public void sendToNonexistentHost() throws Exception { + public void sendToNonexistentServer() throws Exception { // Setup xdsClient to fail on stream creation - XdsClientImpl client = createXdsClient("some.garbage"); + // The Windows CI takes ~11 seconds to resolve "doesnotexist.invalid.". That seems broken, since + // it should take no I/O, but let's limit ourselves to IP literals and hostnames in the hosts + // file. Assume localhost doesn't speak HTTP/2 on the finger port + XdsClientImpl client = createXdsClient("localhost:79"); client.watchXdsResource(XdsListenerResource.getInstance(), LDS_RESOURCE, ldsResourceWatcher); verify(ldsResourceWatcher, Mockito.timeout(5000).times(1)).onError(ArgumentMatchers.any()); assertThat(fakeClock.numPendingTasks()).isEqualTo(1); //retry