Include cause that was used to notify the promise when logging an failed try to notify it.

Motivation:

When a promise is notified that was already added to the ChannelOutboundBuffer and we try to notify it later on we only see a warning that it was notified before. This is often not very useful as we have no idea where it was notified at all. We can do better in case it was failed before (which is most of the times the case) and just also log the cause that was used for it.

Modifications:

Add the cause that was used to notify the promise when we fail to notify it as part of the ChannelOutboundBuffer.

Result:

Easier to debug user errors.
This commit is contained in:
Norman Maurer 2016-03-29 16:00:27 +02:00
parent 35c5664a64
commit 61ae4a3a78

View File

@ -29,6 +29,9 @@ import io.netty.util.internal.PlatformDependent;
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;
@ -671,13 +674,43 @@ public final class ChannelOutboundBuffer {
private static void safeSuccess(ChannelPromise promise) {
if (!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
logger.warn("Failed to mark a promise as success because it is done already: {}", promise);
Throwable err = promise.cause();
if (err == null) {
logger.warn("Failed to mark a promise as success because it has succeeded already: {}", promise);
} else {
logger.warn(
"Failed to mark a promise as success because it has failed already: {}, unnotified cause {}",
promise, stackTraceToString(err));
}
}
}
private static void safeFail(ChannelPromise promise, Throwable cause) {
if (!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) {
logger.warn("Failed to mark a promise as failure because it's done already: {}", promise, cause);
Throwable err = promise.cause();
if (err == null) {
logger.warn("Failed to mark a promise as failure because it has succeeded already: {}", promise, cause);
} 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
}
}
}