You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When there is an encoder in a channel pipeline which is NOT the last handler AND runs in an UnorderedThreadPoolEventExecutor with size > 1, channel.writeAndFlush(...) fails to flush (from my simple investigation probably because the encoded bytes are not yet written - there is a FLUSH event, but no data). When flushing manually after a small delay, it works.
When setting the executor size to 1, it works.
When the encoder it is the last handler, it works
Minimal yet complete reproducer code
importjava.nio.charset.StandardCharsets;
importio.netty.bootstrap.Bootstrap;
importio.netty.bootstrap.ServerBootstrap;
importio.netty.buffer.ByteBuf;
importio.netty.channel.ChannelFuture;
importio.netty.channel.ChannelFutureListener;
importio.netty.channel.ChannelHandlerContext;
importio.netty.channel.ChannelInboundHandlerAdapter;
importio.netty.channel.ChannelInitializer;
importio.netty.channel.ChannelOption;
importio.netty.channel.nio.NioEventLoopGroup;
importio.netty.channel.socket.SocketChannel;
importio.netty.channel.socket.nio.NioServerSocketChannel;
importio.netty.channel.socket.nio.NioSocketChannel;
importio.netty.handler.codec.MessageToByteEncoder;
importio.netty.handler.logging.LogLevel;
importio.netty.handler.logging.LoggingHandler;
importio.netty.util.concurrent.UnorderedThreadPoolEventExecutor;
publicclassNettyBug {
static {
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "trace");
}
privatestaticclassCodecextendsMessageToByteEncoder<String> {
@Overrideprotectedvoidencode(ChannelHandlerContextctx, Stringmsg, ByteBufout) throwsException {
out.writeCharSequence(msg, StandardCharsets.UTF_8);
}
}
publicstaticvoidmain(String[] args) throwsInterruptedException {
// ===== discard + close server =====varserverGroup = newNioEventLoopGroup(1);
varserverBootstrap = newServerBootstrap().group(serverGroup);
serverBootstrap.channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, Integer.valueOf(128))
.handler(newLoggingHandler("ServerAcceptor"));
serverBootstrap.childHandler(newChannelInboundHandlerAdapter() {
@OverridepublicvoidchannelRead(ChannelHandlerContextctx, Objectmsg) {
// Discard the received data silently.System.err.println("OK! Received " + msg);
((ByteBuf) msg).release();
System.err.println("Close");
ctx.close();
}
@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx, Throwablecause) {
// Close the connection when an exception is raised.cause.printStackTrace();
ctx.close();
}
});
serverBootstrap.bind(50005).sync();
// ===== CLIENT =====varclientIOGroup = newNioEventLoopGroup(1);
varclientWorkerGroup = newUnorderedThreadPoolEventExecutor(2); // works with size = 1 !!!varbootstrap = newBootstrap().group(clientIOGroup).channel(NioSocketChannel.class);
bootstrap.handler(newChannelInitializer<SocketChannel>() {
@OverrideprotectedvoidinitChannel(SocketChannelch) throwsException {
varpipeline = ch.pipeline();
pipeline.addLast("frameLogger", newLoggingHandler("first", LogLevel.DEBUG)); // no impact, just for debuggingpipeline.addLast(clientWorkerGroup, newCodec());
pipeline.addLast("finalLogger", newLoggingHandler("second", LogLevel.DEBUG)); // works WITHOUT this handler !!!
}
});
bootstrap.connect("localhost", 50005).addListener(newChannelFutureListener() {
@OverridepublicvoidoperationComplete(ChannelFuturef) throwsException {
f.channel().writeAndFlush("hello").addListener(ChannelFutureListener.CLOSE);
}
});
}
}
Netty version
4.1.106
JVM version (e.g. java -version)
17
OS version (e.g. uname -a)
Windows
The text was updated successfully, but these errors were encountered:
So this is kind of expected in the sense that each handler methods will be called in an "unordered" fashion. As writeAndFlush is just a shortcut for calling write(...) and flush separately you can end up with such a situation
That's what I thought. Big problem, because it prevents running the de/encoder in a separate thread pool if there is anything in the pipeline afterwards.
When there is an encoder in a channel pipeline which is NOT the last handler AND runs in an UnorderedThreadPoolEventExecutor with size > 1, channel.writeAndFlush(...) fails to flush (from my simple investigation probably because the encoded bytes are not yet written - there is a FLUSH event, but no data). When flushing manually after a small delay, it works.
Minimal yet complete reproducer code
Netty version
4.1.106
JVM version (e.g.
java -version
)17
OS version (e.g.
uname -a
)Windows
The text was updated successfully, but these errors were encountered: