[#1501] Fix NPE correctly which could accour if ChannelOutboundBuffer.fail(..) triggered another call to ChannelOutboundBuffer.fail(...)

This commit is contained in:
Norman Maurer 2013-07-02 09:58:41 +02:00
parent 8dfbcbda29
commit 5437835832

View File

@ -41,6 +41,7 @@ final class ChannelOutboundBuffer {
private int head; private int head;
private int tail; private int tail;
private boolean inFail;
private final AbstractChannel channel; private final AbstractChannel channel;
private int pendingOutboundBytes; private int pendingOutboundBytes;
@ -213,33 +214,38 @@ final class ChannelOutboundBuffer {
} }
void fail(Throwable cause) { void fail(Throwable cause) {
if (currentPromise == null) { // We need to check if we already process the fail here as the notification of the future may trigger some
if (!next()) { // other event which will also call ChannelOutboundBuffer and so set currentMessage and currentPromise to
return; // null.
} // See https://github.com/netty/netty/issues/1501
if (inFail) {
return;
} }
try {
do { inFail = true;
if (!(currentPromise instanceof VoidChannelPromise) && !currentPromise.tryFailure(cause)) { if (currentPromise == null) {
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
if (!next()) { if (!next()) {
return; return;
} }
} }
// Release all failed messages. do {
try { if (!(currentPromise instanceof VoidChannelPromise) && !currentPromise.tryFailure(cause)) {
for (int i = currentMessageIndex; i < currentMessages.size(); i++) { logger.warn("Promise done already:", cause);
Object msg = currentMessages.get(i);
ReferenceCountUtil.release(msg);
} }
} finally {
currentMessages.recycle(); // Release all failed messages.
} try {
} while(next()); for (int i = currentMessageIndex; i < currentMessages.size(); i++) {
Object msg = currentMessages.get(i);
ReferenceCountUtil.release(msg);
}
} finally {
currentMessages.recycle();
}
} while(next());
} finally {
inFail = false;
}
} }
} }