From 54378358327ac0fdaa2982114f74a17ec4cfe0ad Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Tue, 2 Jul 2013 09:58:41 +0200 Subject: [PATCH] [#1501] Fix NPE correctly which could accour if ChannelOutboundBuffer.fail(..) triggered another call to ChannelOutboundBuffer.fail(...) --- .../netty/channel/ChannelOutboundBuffer.java | 48 +++++++++++-------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java index ea4c5331c0..3da56e62cb 100644 --- a/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java +++ b/transport/src/main/java/io/netty/channel/ChannelOutboundBuffer.java @@ -41,6 +41,7 @@ final class ChannelOutboundBuffer { private int head; private int tail; + private boolean inFail; private final AbstractChannel channel; private int pendingOutboundBytes; @@ -213,33 +214,38 @@ final class ChannelOutboundBuffer { } void fail(Throwable cause) { - if (currentPromise == null) { - if (!next()) { - return; - } + // We need to check if we already process the fail here as the notification of the future may trigger some + // other event which will also call ChannelOutboundBuffer and so set currentMessage and currentPromise to + // null. + // See https://github.com/netty/netty/issues/1501 + if (inFail) { + return; } - - do { - if (!(currentPromise instanceof VoidChannelPromise) && !currentPromise.tryFailure(cause)) { - logger.warn("Promise done already:", cause); - } else { - // We need to check for next here as the notification of the future may trigger some other event - // which will also call ChannelOutboundBuffer and so set currentMessage and currentPromise to null. - // See https://github.com/netty/netty/issues/1501 + try { + inFail = true; + if (currentPromise == null) { if (!next()) { return; } } - // Release all failed messages. - try { - for (int i = currentMessageIndex; i < currentMessages.size(); i++) { - Object msg = currentMessages.get(i); - ReferenceCountUtil.release(msg); + do { + if (!(currentPromise instanceof VoidChannelPromise) && !currentPromise.tryFailure(cause)) { + logger.warn("Promise done already:", cause); } - } finally { - currentMessages.recycle(); - } - } while(next()); + + // Release all failed messages. + try { + for (int i = currentMessageIndex; i < currentMessages.size(); i++) { + Object msg = currentMessages.get(i); + ReferenceCountUtil.release(msg); + } + } finally { + currentMessages.recycle(); + } + } while(next()); + } finally { + inFail = false; + } } }