[#1242] Fix infinity-loop which was triggered when a write failed and AioSocketChannel was used

This commit is contained in:
Norman Maurer 2013-04-10 15:39:58 +02:00
parent 3b8673733e
commit 725156f082

View File

@ -76,7 +76,12 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
private boolean readInProgress; private boolean readInProgress;
private boolean inDoBeginRead; private boolean inDoBeginRead;
private boolean readAgain; private boolean readAgain;
private boolean writeInProgress;
private static final int NO_WRITE_IN_PROGRESS = 0;
private static final int WRITE_IN_PROGRESS = 1;
private static final int WRITE_FAILED = -2;
private int writeInProgress;
private boolean inDoFlushByteBuffer; private boolean inDoFlushByteBuffer;
/** /**
@ -246,7 +251,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
@Override @Override
protected void doFlushByteBuffer(ByteBuf buf) throws Exception { protected void doFlushByteBuffer(ByteBuf buf) throws Exception {
if (inDoFlushByteBuffer || writeInProgress) { if (inDoFlushByteBuffer || writeInProgress != NO_WRITE_IN_PROGRESS) {
return; return;
} }
@ -263,7 +268,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
// discardReadBytes() later, modifying the readerIndex and the writerIndex unexpectedly. // discardReadBytes() later, modifying the readerIndex and the writerIndex unexpectedly.
buf.discardReadBytes(); buf.discardReadBytes();
writeInProgress = true; writeInProgress = WRITE_IN_PROGRESS;
if (buf.nioBufferCount() == 1) { if (buf.nioBufferCount() == 1) {
javaChannel().write( javaChannel().write(
buf.nioBuffer(), config.getWriteTimeout(), TimeUnit.MILLISECONDS, this, WRITE_HANDLER); buf.nioBuffer(), config.getWriteTimeout(), TimeUnit.MILLISECONDS, this, WRITE_HANDLER);
@ -279,7 +284,13 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
} }
} }
if (writeInProgress) { if (writeInProgress != NO_WRITE_IN_PROGRESS) {
if (writeInProgress == WRITE_FAILED) {
// failed because of an exception so reset state and break out of the loop now
// See #1242
writeInProgress = NO_WRITE_IN_PROGRESS;
break;
}
// JDK decided to write data (or notify handler) later. // JDK decided to write data (or notify handler) later.
buf.suspendIntermediaryDeallocations(); buf.suspendIntermediaryDeallocations();
break; break;
@ -368,7 +379,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
@Override @Override
protected void completed0(T result, AioSocketChannel channel) { protected void completed0(T result, AioSocketChannel channel) {
channel.writeInProgress = false; channel.writeInProgress = NO_WRITE_IN_PROGRESS;
ByteBuf buf = channel.unsafe().directOutboundContext().outboundByteBuffer(); ByteBuf buf = channel.unsafe().directOutboundContext().outboundByteBuffer();
if (buf.refCnt() == 0) { if (buf.refCnt() == 0) {
@ -407,7 +418,7 @@ public class AioSocketChannel extends AbstractAioChannel implements SocketChanne
@Override @Override
protected void failed0(Throwable cause, AioSocketChannel channel) { protected void failed0(Throwable cause, AioSocketChannel channel) {
channel.writeInProgress = false; channel.writeInProgress = WRITE_FAILED;
channel.flushFutureNotifier.notifyFlushFutures(cause); channel.flushFutureNotifier.notifyFlushFutures(cause);
// Check if the exception was raised because of an InterruptedByTimeoutException which means that the // Check if the exception was raised because of an InterruptedByTimeoutException which means that the