Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

netty: prevent interruption during bind from leaking channel #6867

Merged
merged 1 commit into from Mar 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 30 additions & 0 deletions core/src/test/java/io/grpc/internal/AbstractTransportTest.java
Expand Up @@ -400,6 +400,36 @@ public void serverAlreadyListening() throws Exception {
server2.start(new MockServerListener());
}

@Test
public void serverStartInterrupted() throws Exception {
client = null;

// Just get free port
server.start(serverListener);
int port = -1;
SocketAddress addr = server.getListenSocketAddress();
if (addr instanceof InetSocketAddress) {
port = ((InetSocketAddress) addr).getPort();
}
assumeTrue("transport is not using InetSocketAddress", port != -1);
server.shutdown();

server = Iterables.getOnlyElement(newServer(port, Arrays.asList(serverStreamTracerFactory)));
boolean success;
Thread.currentThread().interrupt();
try {
server.start(serverListener);
success = true;
} catch (Exception ex) {
success = false;
} finally {
Thread.interrupted(); // clear interruption
}
assumeTrue("apparently start is not impacted by interruption, so nothing to test", !success);
// second time should not throw, as the first time should not have bound to the port
server.start(serverListener);
}

@Test
public void openStreamPreventsTermination() throws Exception {
server.start(serverListener);
Expand Down
10 changes: 4 additions & 6 deletions netty/src/main/java/io/grpc/netty/NettyServer.java
Expand Up @@ -242,12 +242,10 @@ public void operationComplete(ChannelFuture future) throws Exception {
});
// Bind and start to accept incoming connections.
ChannelFuture future = b.bind(address);
try {
future.await();
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted waiting for bind");
}
// We'd love to observe interruption, but if interrupted we will need to close the channel,
// which itself would need an await() to guarantee the port is not used when the method returns.
// See #6850
future.awaitUninterruptibly();
if (!future.isSuccess()) {
throw new IOException("Failed to bind", future.cause());
}
Expand Down