diff --git a/common/src/main/java/io/netty/util/internal/ThrowableUtils.java b/common/src/main/java/io/netty/util/internal/ThrowableUtils.java new file mode 100644 index 0000000000..a592862584 --- /dev/null +++ b/common/src/main/java/io/netty/util/internal/ThrowableUtils.java @@ -0,0 +1,48 @@ +/* + * Copyright 2016 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ +package io.netty.util.internal; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; + +public final class ThrowableUtils { + + /** + *

Gets the stack trace from a Throwable as a String.

+ * + * @param throwable the Throwable to be examined + * @return the stack trace as generated by the exception's + * printStackTrace(PrintWriter) method + */ + public static String stackTraceToString(Throwable cause) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrintStream pout = new PrintStream(out); + cause.printStackTrace(pout); + pout.flush(); + try { + return new String(out.toByteArray()); + } finally { + try { + out.close(); + } catch (IOException ignore) { + // ignore as should never happen + } + } + } + + private ThrowableUtils() { } +} diff --git a/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java b/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java index 44bbda5010..2e504bfa52 100644 --- a/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java +++ b/transport/src/main/java/io/netty/channel/AbstractChannelHandlerContext.java @@ -16,13 +16,14 @@ package io.netty.channel; import io.netty.buffer.ByteBufAllocator; -import io.netty.util.DefaultAttributeMap; -import io.netty.util.ResourceLeakHint; import io.netty.util.Attribute; import io.netty.util.AttributeKey; +import io.netty.util.DefaultAttributeMap; import io.netty.util.Recycler; import io.netty.util.ReferenceCountUtil; +import io.netty.util.ResourceLeakHint; import io.netty.util.concurrent.EventExecutor; +import io.netty.util.internal.ThrowableUtils; import io.netty.util.internal.ObjectUtil; import io.netty.util.internal.StringUtil; import io.netty.util.internal.SystemPropertyUtil; @@ -274,11 +275,18 @@ abstract class AbstractChannelHandlerContext extends DefaultAttributeMap if (isAdded()) { try { handler().exceptionCaught(this, cause); - } catch (Throwable t) { - if (logger.isWarnEnabled()) { + } catch (Throwable error) { + if (logger.isDebugEnabled()) { + logger.debug( + "An exception {}" + + "was thrown by a user handler's exceptionCaught() " + + "method while handling the following exception:", + ThrowableUtils.stackTraceToString(error), cause); + } else if (logger.isWarnEnabled()) { logger.warn( - "An exception was thrown by a user handler's " + - "exceptionCaught() method while handling the following exception:", cause); + "An exception '{}' [enable DEBUG level for full stacktrace] " + + "was thrown by a user handler's exceptionCaught() " + + "method while handling the following exception:", error, cause); } } } else { diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java index 9f757d8279..825e9b7874 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java @@ -25,12 +25,10 @@ import io.netty.util.ReferenceCountUtil; import io.netty.util.concurrent.FastThreadLocal; import io.netty.util.internal.InternalThreadLocalMap; import io.netty.util.internal.PlatformDependent; +import io.netty.util.internal.ThrowableUtils; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.PrintStream; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; import java.util.Arrays; @@ -679,7 +677,7 @@ public final class ChannelOutboundBuffer { } else { logger.warn( "Failed to mark a promise as success because it has failed already: {}, unnotified cause {}", - promise, stackTraceToString(err)); + promise, ThrowableUtils.stackTraceToString(err)); } } } @@ -692,23 +690,7 @@ public final class ChannelOutboundBuffer { } else { logger.warn( "Failed to mark a promise as failure because it hass failed already: {}, unnotified cause {}", - promise, stackTraceToString(err), cause); - } - } - } - - private static String stackTraceToString(Throwable cause) { - ByteArrayOutputStream out = new ByteArrayOutputStream(); - PrintStream pout = new PrintStream(out); - cause.printStackTrace(pout); - pout.flush(); - try { - return new String(out.toByteArray()); - } finally { - try { - out.close(); - } catch (IOException ignore) { - // ignore as should never happen + promise, ThrowableUtils.stackTraceToString(err), cause); } } } diff --git a/transport/src/main/java/io/netty/channel/CombinedChannelDuplexHandler.java b/transport/src/main/java/io/netty/channel/CombinedChannelDuplexHandler.java index e507e99b57..ba78f853b8 100644 --- a/transport/src/main/java/io/netty/channel/CombinedChannelDuplexHandler.java +++ b/transport/src/main/java/io/netty/channel/CombinedChannelDuplexHandler.java @@ -19,6 +19,7 @@ import io.netty.buffer.ByteBufAllocator; import io.netty.util.Attribute; import io.netty.util.AttributeKey; import io.netty.util.concurrent.EventExecutor; +import io.netty.util.internal.ThrowableUtils; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -142,10 +143,17 @@ public class CombinedChannelDuplexHandler