[#2761] ChannelOutboundBuffer can cause data-corruption because of caching ByteBuffers

Motivation:

We cache the ByteBuffers in ChannelOutboundBuffer.nioBuffers() for the Entries in the ChannelOutboundBuffer to reduce some overhead. The problem is this can lead to data-corruption if an incomplete write happens and next time we try to do a non-gathering write.

To fix this we should remove the caching which does not help a lot anyway and just make the code buggy.

Modifications:

Remove the caching of ByteBuffers.

Result:

No more data-corruption.
This commit is contained in:
Norman Maurer 2014-08-13 11:06:03 +02:00
parent ef3c030013
commit 4059c9f354

View File

@ -352,31 +352,17 @@ public final class ChannelOutboundBuffer {
if (readableBytes > 0) {
nioBufferSize += readableBytes;
int count = entry.count;
if (count == -1) {
//noinspection ConstantValueVariableUse
entry.count = count = buf.nioBufferCount();
}
int count = buf.nioBufferCount();
int neededSpace = nioBufferCount + count;
if (neededSpace > nioBuffers.length) {
nioBuffers = expandNioBufferArray(nioBuffers, neededSpace, nioBufferCount);
NIO_BUFFERS.set(threadLocalMap, nioBuffers);
}
if (count == 1) {
ByteBuffer nioBuf = entry.buf;
if (nioBuf == null) {
// cache ByteBuffer as it may need to create a new ByteBuffer instance if its a
// derived buffer
entry.buf = nioBuf = buf.internalNioBuffer(readerIndex, readableBytes);
}
ByteBuffer nioBuf = buf.internalNioBuffer(readerIndex, readableBytes);
nioBuffers[nioBufferCount ++] = nioBuf;
} else {
ByteBuffer[] nioBufs = entry.bufs;
if (nioBufs == null) {
// cached ByteBuffers as they may be expensive to create in terms
// of Object allocation
entry.bufs = nioBufs = buf.nioBuffers();
}
ByteBuffer[] nioBufs = buf.nioBuffers(readerIndex, readableBytes);
nioBufferCount = fillBufferArray(nioBufs, nioBuffers, nioBufferCount);
}
}
@ -586,13 +572,10 @@ public final class ChannelOutboundBuffer {
private final Handle handle;
Entry next;
Object msg;
ByteBuffer[] bufs;
ByteBuffer buf;
ChannelPromise promise;
long progress;
long total;
int pendingSize;
int count = -1;
boolean cancelled;
private Entry(Handle handle) {
@ -620,8 +603,6 @@ public final class ChannelOutboundBuffer {
pendingSize = 0;
total = 0;
progress = 0;
bufs = null;
buf = null;
return pSize;
}
return 0;
@ -629,14 +610,11 @@ public final class ChannelOutboundBuffer {
void recycle() {
next = null;
bufs = null;
buf = null;
msg = null;
promise = null;
progress = 0;
total = 0;
pendingSize = 0;
count = -1;
cancelled = false;
RECYCLER.recycle(this, handle);
}