xds: terminate XdsServer start() thread when shutdownNow() is called

`XdsServerWrapper.start()` [blocks](https://github.com/grpc/grpc-java/blob/master/xds/src/main/java/io/grpc/xds/XdsServerWrapper.java#L162) until `LdsResourceWatcher`'s callback is called. If no callback is called due to whatever issue of the XdsClient, the server start() will be stuck forever, even we call `shutdownNow()`.

Changing the `shutdownNow()` behavior to unblock `start()` immediately.
This commit is contained in:
ZHANG Dapeng 2021-11-17 19:54:40 -08:00 committed by GitHub
parent 5a3b8e2141
commit dd0db6cf41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 0 deletions

View File

@ -224,6 +224,7 @@ final class XdsServerWrapper extends Server {
delegate.shutdownNow();
}
internalShutdown();
initialStartFuture.set(new IOException("server is forcefully shut down"));
}
});
return this;

View File

@ -76,6 +76,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -116,6 +117,11 @@ public class XdsServerWrapperTest {
filterRegistry, executor.getScheduledExecutorService());
}
@After
public void tearDown() {
xdsServerWrapper.shutdownNow();
}
@Test
public void testBootstrap_notV3() throws Exception {
Bootstrapper.BootstrapInfo b =
@ -324,6 +330,33 @@ public class XdsServerWrapperTest {
assertThat(xdsServerWrapper.isTerminated()).isTrue();
}
@Test
public void shutdownNow_startThreadShouldNotLeak() throws Exception {
final SettableFuture<Server> start = SettableFuture.create();
Executors.newSingleThreadExecutor()
.execute(
new Runnable() {
@Override
public void run() {
try {
start.set(xdsServerWrapper.start());
} catch (Exception ex) {
start.setException(ex);
}
}
});
assertThat(xdsClient.ldsResource.get(5, TimeUnit.SECONDS))
.isEqualTo("grpc/server?udpa.resource.listening_address=0.0.0.0:1");
xdsServerWrapper.shutdownNow();
try {
start.get(5, TimeUnit.SECONDS);
fail("should have thrown but not");
} catch (ExecutionException ex) {
assertThat(ex).hasCauseThat().isInstanceOf(IOException.class);
assertThat(ex).hasCauseThat().hasMessageThat().isEqualTo("server is forcefully shut down");
}
}
@Test
public void initialStartIoException() throws Exception {
final SettableFuture<Server> start = SettableFuture.create();