Reputation: 1009
I got this warning in my log:
Nov 02, 2016 12:07:20 AM io.netty.channel.DefaultChannelPipeline onUnhandledInboundException
WARNUNG: An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
java.util.concurrent.TimeoutException
That are my ChannelHandlers:
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
ch.pipeline().addLast(new TimeoutHandler(TIME_OUT_SECONDS));
ch.pipeline().addLast(new ServerCommunicationHandler(messageHandler));
}
My TimeoutHandler throws a TimeoutException if there was no read for the last 15 seconds. And in my last handler, the ServerCommunicationHandler, i have overridden the exeptionCaught function:
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
ctx.close();
}
So if i understand right, i do not rethrow the exception to the end of the pipeline, because my last handler processes the exception correctly, doesn't it?
Why do i get this warning?
I use Netty 4.1.6.Final
Upvotes: 7
Views: 40117
Reputation: 1
Maybe it's an exception thrown due to incomplete data received? My project also encountered this problem recently, because the received data code is GBK and I use utf8, so when intercepting the data in the corresponding location, I threw a subscript out of range error and caused this error.
screenshot of error message which is neither English nor printable with ISO-8859 charset
Upvotes: 0
Reputation: 1281
This can be caused by your TimeoutHandler throwing the TimeoutException after the channel has been closed. It can happen because once a channel is closed all the ChannelHandlers will be removed (unregistered), but the ChannelHandlerContext still has a reference to the pipeline, so if you close a channel and then fire an event on the ctx
there won't be any handlers to intercept the event.
I was able to recreate the error you see by writing a simple/broken TimeoutHandler:
@RequiredArgsConstructor
private static class TimeoutHandler extends ChannelInboundHandlerAdapter {
private final int timeoutSeconds;
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
ctx.executor().schedule(
// This exception can still be fired once the channel is closed and all handlers removed
() -> ctx.fireExceptionCaught(new TimeoutException()),
timeoutSeconds, TimeUnit.SECONDS);
super.channelRegistered(ctx);
}
}
Have you considered using the Netty ReadTimeoutHandler instead of writing your own?
If you really want to write your own, make sure you are canceling your timer when the channel goes inactive. You can see how IdleStateHandler does this.
Upvotes: 6