Skip to content

Why can't I shutdown the Netty Client ? #7694

@raomuyang

Description

@raomuyang

Expected behavior

I have launched a netty server and establish a connection with it via netty client. The client sends a message to the server, while the server will feedback and close context (Channel), when the client got a message from the server, it will close channel and shutdown EventLoopGroup, and then exit the program.

Actual behavior

However, all the channel was closed, but the EventLoopGroup unable to shutdown (isShutdown always false), no matter client or server, the main thread blocked.

Steps to reproduce

The code as follow.

Minimal yet complete reproducer code (or URL to code)

  • Server
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.ReferenceCountUtil;

public class TestServer {
    public static final int PORT = 12345;

    public static void main(String[] args) throws InterruptedException {
        ServerBootstrap bootstrap = new ServerBootstrap();
        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup(1);
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new Initializer());

        ChannelFuture future = bootstrap.bind(PORT).sync();
        future.channel().closeFuture().sync();

        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }

    static class Initializer extends ChannelInitializer<SocketChannel> {
        private static final StringDecoder DECODER = new StringDecoder();
        private static final StringEncoder ENCODER = new StringEncoder();

        @Override
        protected void initChannel(SocketChannel channel) throws Exception {
            ChannelPipeline pipeline = channel.pipeline();
            pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            pipeline.addLast(DECODER);
            pipeline.addLast(ENCODER);
            pipeline.addLast(new Handler());
        }
    }

    static class Handler extends SimpleChannelInboundHandler<String> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            System.out.println("server:" + msg);
            ctx.writeAndFlush(msg + "\r\n");
            ReferenceCountUtil.release(msg);
            ctx.close();
        }
    }
}
  • Client
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.ReferenceCountUtil;

public class TestClient {

    public static void main(String[] args) throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        EventLoopGroup group = new NioEventLoopGroup(1);
        ChannelFuture future = bootstrap.group(group)
                .handler(new Initializer())
                .option(ChannelOption.SO_KEEPALIVE, true)
                .channel(NioSocketChannel.class)
                .connect("127.0.0.1", TestServer.PORT);

        future.sync().channel().writeAndFlush("abcdef\r\n");
        future.channel().closeFuture().sync();
        group.shutdownGracefully();
        System.out.println("closed: " + !future.channel().isOpen() + "/shutdown:" + group.isShutdown());
    }

    static class Initializer extends ChannelInitializer<SocketChannel> {
        private static final StringDecoder DECODER = new StringDecoder();
        private static final StringEncoder ENCODER = new StringEncoder();

        @Override
        protected void initChannel(SocketChannel channel) throws Exception {
            ChannelPipeline pipeline = channel.pipeline();
            pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            pipeline.addLast(DECODER);
            pipeline.addLast(ENCODER);
            pipeline.addLast(new Handler());
        }
    }

    static class Handler extends SimpleChannelInboundHandler<String> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            System.out.println("client:" + msg);
            ctx.writeAndFlush(msg);
            ReferenceCountUtil.release(msg);
            ctx.close();
        }
    }
}

Netty version

<dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.20.Final</version>
        </dependency>

JVM version (e.g. java -version)

java version "1.8.0_131"

OS version (e.g. uname -a)

  • Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-104-generic x86_64)
  • OSX 10.13.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions