Skip to content

Commit

Permalink
netty: prevent interruption during bind from leaking channel
Browse files Browse the repository at this point in the history
Fixes #6850
  • Loading branch information
ejona86 committed Mar 28, 2020
1 parent 0b4503e commit 2c250ac
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 6 deletions.
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

0 comments on commit 2c250ac

Please sign in to comment.