From 2a3ae36bd3730058d00564bca7e7502f84d099df Mon Sep 17 00:00:00 2001 From: Eric Anderson Date: Thu, 3 Sep 2015 15:53:31 -0700 Subject: [PATCH] Only release event loops when unused Resolves #926. Transports can still be alive when the Server shuts down, but they are using the worker event loops. Only release the worker event loops when all transport's channels are closed. --- .../main/java/io/grpc/netty/NettyServer.java | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/netty/src/main/java/io/grpc/netty/NettyServer.java b/netty/src/main/java/io/grpc/netty/NettyServer.java index bd083e49e9..f1ba4df279 100644 --- a/netty/src/main/java/io/grpc/netty/NettyServer.java +++ b/netty/src/main/java/io/grpc/netty/NettyServer.java @@ -48,6 +48,8 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.ServerChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.ssl.SslContext; +import io.netty.util.AbstractReferenceCounted; +import io.netty.util.ReferenceCounted; import java.io.IOException; import java.net.SocketAddress; @@ -74,6 +76,7 @@ public class NettyServer implements Server { private Channel channel; private final int flowControlWindow; private final int maxMessageSize; + private final ReferenceCounted eventLoopReferenceCounter = new EventLoopReferenceCounter(); NettyServer(SocketAddress address, Class channelType, @Nullable EventLoopGroup bossGroup, @Nullable EventLoopGroup workerGroup, @@ -108,6 +111,12 @@ public class NettyServer implements Server { b.childHandler(new ChannelInitializer() { @Override public void initChannel(Channel ch) throws Exception { + eventLoopReferenceCounter.retain(); + ch.closeFuture().addListener(new ChannelFutureListener() { + public void operationComplete(ChannelFuture future) { + eventLoopReferenceCounter.release(); + } + }); NettyServerTransport transport = new NettyServerTransport(ch, sslContext, maxStreamsPerConnection, flowControlWindow, maxMessageSize); @@ -142,7 +151,7 @@ public class NettyServer implements Server { log.log(Level.WARNING, "Error shutting down server", future.cause()); } listener.serverShutdown(); - releaseSharedGroups(); + eventLoopReferenceCounter.release(); } }); } @@ -156,20 +165,28 @@ public class NettyServer implements Server { } } - private void releaseSharedGroups() { - try { - if (usingSharedBossGroup && bossGroup != null) { - SharedResourceHolder.release(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP, bossGroup); - } - } finally { - bossGroup = null; + class EventLoopReferenceCounter extends AbstractReferenceCounted { + @Override + protected void deallocate() { try { - if (usingSharedWorkerGroup && workerGroup != null) { - SharedResourceHolder.release(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP, workerGroup); + if (usingSharedBossGroup && bossGroup != null) { + SharedResourceHolder.release(Utils.DEFAULT_BOSS_EVENT_LOOP_GROUP, bossGroup); } } finally { - workerGroup = null; + bossGroup = null; + try { + if (usingSharedWorkerGroup && workerGroup != null) { + SharedResourceHolder.release(Utils.DEFAULT_WORKER_EVENT_LOOP_GROUP, workerGroup); + } + } finally { + workerGroup = null; + } } } + + @Override + public ReferenceCounted touch(Object hint) { + return this; + } } }