图片是在钉钉的[Arthas开源交流群2]群里别人发出来的, 我看到之后就去查看了源码,自己模拟了一下,发现代码的确存在问题.

2.1 在连接服务端时,客户端A使用了EventLoopGroup.
2.2 com.alibaba.arthas.tunnel.client.TunnelClientSocketClientHandler类在处理读请求时,启动了com.alibaba.arthas.tunnel.client.ForwardClient类. ForwardClient类中也创建了一个客户端B, 而客户端B使用的EventLoopGroup与客户端A使用的EventLoopGroup是同一个.
2.3 客户端B在调用b.connect(tunnelServerURI.getHost(), port).sync().channel()时候调用了sync()方法. 继续调用await(),
调用checkDeadLock()
2.4 每次服务端给客户端A发送数据之后,客户端A在读取数据过程都会创建新的客户端. 由于所有的客户端使用的是同一个EventLoopGroup, 虽然Netty底层是通过轮询的方式,每次给客户端从EventLoopGroup分配一个EventLoop. 假如EventLoopGroup大小=8,当服务端发送第九次数据给客户端A的时候,这个时候已经存在9个客户端了,那么第9个客户端和第1个
客户端使用的就是同一个EventLoop, 这样在调用checkDeadLock()时候就会报错.
其实虽然两个客户端使用了同一个EventLoop,也不见得一定报错,但是源码中使用channel = b.connect(tunnelServerURI.getHost(), port).sync().channel()这样的书写方式就会报错.改成类似这样的写法就可以了
ChannelFuture channelFuture = b.connect("127.0.0.1", 8080);
channelFuture.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture channelFuture) throws Exception {
Channel channel = channelFuture.sync().channel();
}
});
可以优化成使用channelFuture.addListener方式
分析非常清楚,欢迎提交PR来修复。
@infuq 感谢!昨天请教后,我修改了 ForwardClient 的 group 参数 ,重新测试了一下,没有再发现deadlock问题了,改动如下:
ForwardClient forwardClient = new ForwardClient(forwardUri,
new URI(this.tunnelClient.getLocalServerUrl()), new NioEventLoopGroup());
forwardClient.start();
但是今天的测试依然存在问题,页面刷新几次,还是有一定概率连接不上控制台了。定位了一下卡在了ForwardClientSocketClientHandler#connectLocalServer ,而这个位置正常情况不会卡住。
handshakeFuture.sync();

@infuq 你好,再补充一点,tunnel server 也有这个问题,你提 PR 的时候注意一下,之前的异常栈是 tunnel client 的,server 端异常栈如下
io.netty.util.concurrent.BlockingOperationException: DefaultPromise@4f3ffb6f(incomplete)
at io.netty.util.concurrent.DefaultPromise.checkDeadLock(DefaultPromise.java:461) [netty-common-4.1.45.Final.jar:4.1.45.Final]
at io.netty.util.concurrent.DefaultPromise.await0(DefaultPromise.java:666) [netty-common-4.1.45.Final.jar:4.1.45.Final]
at io.netty.util.concurrent.DefaultPromise.awaitUninterruptibly(DefaultPromise.java:304) [netty-common-4.1.45.Final.jar:4.1.45.Final]
at com.alibaba.arthas.tunnel.server.TunnelSocketFrameHandler.connectArthas(TunnelSocketFrameHandler.java:147) ~[classes/:na]
at com.alibaba.arthas.tunnel.server.TunnelSocketFrameHandler.userEventTriggered(TunnelSocketFrameHandler.java:59) ~[classes/:na]
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:344) [netty-transport-4.1.45.Final.jar:4.1.45.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeUserEventTriggered(AbstractChannelHandlerContext.java:330) [netty-transport-4.1.45.Final.jar:4.1.45.Final]
at io.netty.channel.AbstractChannelHandlerContext.fireUserEventTriggered(AbstractChannelHandlerContext.java:322) [netty-transport-4.1.45.Final.jar:4.1.45.Final]
已经修复了,欢迎测试验证。
Most helpful comment
已经修复了,欢迎测试验证。