exceptionCaught error handling write back response causes exception and infiniteLoop of calling exceptionCaught

≡放荡痞女 提交于 2019-12-13 02:30:34

问题


I'm trying to genericize my error handling for HTTP requests, and always respond with an actual error HTTP code and relevant message.

Here is my issue: in my Handler which extends SimpleChannelUpstreamHandler, exceptionCaught is fired when an exception is thrown anywhere in the stack. That's good. The bad part is that when I try to write out a response to the client with an appropriate HTTP code and response, the write causes an exception, and then the program goes into an infinite loop with calling exceptionCaught over and over again.

This has to be a commonly done task. How can I do it correctly?

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent event)
        throws Exception {

    try{
        logger.error("Error in handling call: ", event.getCause());
        HttpResponse httpResponse = buildHttpResponseObject(UNAUTHORIZED, new StringBuilder("Test"), false, null);

        // Write the response.
        // for some reason calling this next line causes an infinite loop of exceptionCaught, even with the
        // catch below.  No idea why.  Still investigating.  In the meantime, we don't have custom error code responses. 
        ChannelFuture future = event.getChannel().write(httpResponse);

        // Close the connection after the write operation is done, even if it's a keep-alive.
        future.addListener(ChannelFutureListener.CLOSE);
    }
    catch(Exception t){            
        logger.error("Unable to customize error response. ", t);
        event.getChannel().close();

    }
}

Here are the exceptions:

38161 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call: 
javax.net.ssl.SSLHandshakeException: null cert chain
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1364)
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513)
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:790)
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758)
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:931)
    at org.jboss.netty.handler.ssl.SslHandler.decode(SslHandler.java:649)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.callDecode(FrameDecoder.java:288)
    at org.jboss.netty.handler.codec.frame.FrameDecoder.messageReceived(FrameDecoder.java:207)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: javax.net.ssl.SSLHandshakeException: null cert chain
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1639)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:278)
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:266)
    at sun.security.ssl.ServerHandshaker.clientCertificate(ServerHandshaker.java:1627)
    at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:176)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:808)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:806)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1301)
    at org.jboss.netty.handler.ssl.SslHandler$3.run(SslHandler.java:1060)
    at org.jboss.netty.handler.ssl.ImmediateExecutor.execute(ImmediateExecutor.java:31)
    at org.jboss.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1057)
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:947)
    ... 11 more
38177 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call: 
java.lang.IllegalStateException: cannot send more responses than requests
    at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
38177 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call: 
java.lang.IllegalStateException: cannot send more responses than requests
    at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
38224 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call: 
java.lang.IllegalStateException: cannot send more responses than requests
    at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
38255 [New I/O server worker #1-1] ERROR nettytests.http.snoop.HttpSnoopServerHandler - Error in handling call: 
java.lang.IllegalStateException: cannot send more responses than requests
    at org.jboss.netty.handler.codec.http.HttpContentEncoder.writeRequested(HttpContentEncoder.java:104)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.write(Channels.java:605)
    at org.jboss.netty.channel.Channels.write(Channels.java:572)
    at org.jboss.netty.channel.AbstractChannel.write(AbstractChannel.java:245)
    at nettytests.http.snoop.HttpSnoopServerHandler.exceptionCaught(HttpSnoopServerHandler.java:201)
    at nettytests.logger.RequestAuditLogger.handleUpstream(RequestAuditLogger.java:32)
    at org.jboss.netty.handler.codec.replay.ReplayingDecoder.exceptionCaught(ReplayingDecoder.java:456)
    at org.jboss.netty.handler.ssl.SslHandler.exceptionCaught(SslHandler.java:554)
    at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:426)
    at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:47)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:268)
    at org.jboss.netty.channel.Channels.fireMessageReceived(Channels.java:255)
    at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:343)
    at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:274)
    at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:194)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)

... repeat ad infinitum.


回答1:


Infinity loop is bad.. what I noticed is that you call Channel.close() in the finally block. This will most times happen before you can write something to the Channel. You should use the

future.addListener(ChannelFutureListener.CLOSE);

To Close the channel after you have written something. This should even get called on an Exception



来源:https://stackoverflow.com/questions/9592591/exceptioncaught-error-handling-write-back-response-causes-exception-and-infinite

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!