Fix an infinite loop when writing a zero-length FileRegion
Related: #2964 Motivation: Writing a zero-length FileRegion to an NIO channel will lead to an infinite loop. Modification: - Do not write a zero-length FileRegion by protecting with proper 'if'. - Update the testsuite Result: Another bug fixed
This commit is contained in:
parent
582f2e82ec
commit
0eb059bf58
@ -134,16 +134,23 @@ public class SocketFileRegionTest extends AbstractSocketTest {
|
||||
Channel cc = cb.connect().sync().channel();
|
||||
FileRegion region = new DefaultFileRegion(
|
||||
new FileInputStream(file).getChannel(), startOffset, data.length - bufferSize);
|
||||
// Do write ByteBuf and FileRegion to be sure that mixed writes work
|
||||
FileRegion emptyRegion = new DefaultFileRegion(new FileInputStream(file).getChannel(), 0, 0);
|
||||
|
||||
// Do write ByteBuf and then FileRegion to ensure that mixed writes work
|
||||
// Also, write an empty FileRegion to test if writing an empty FileRegion does not cause any issues.
|
||||
//
|
||||
// See https://github.com/netty/netty/issues/2769
|
||||
// https://github.com/netty/netty/issues/2964
|
||||
if (voidPromise) {
|
||||
assertEquals(cc.voidPromise(), cc.write(Unpooled.wrappedBuffer(data, 0, bufferSize), cc.voidPromise()));
|
||||
assertEquals(cc.voidPromise(), cc.write(emptyRegion, cc.voidPromise()));
|
||||
assertEquals(cc.voidPromise(), cc.writeAndFlush(region, cc.voidPromise()));
|
||||
} else {
|
||||
assertNotEquals(cc.voidPromise(), cc.write(Unpooled.wrappedBuffer(data, 0, bufferSize)));
|
||||
assertNotEquals(cc.voidPromise(), cc.write(emptyRegion));
|
||||
assertNotEquals(cc.voidPromise(), cc.writeAndFlush(region));
|
||||
}
|
||||
|
||||
while (sh.counter < data.length) {
|
||||
if (sh.exception.get() != null) {
|
||||
break;
|
||||
|
@ -219,27 +219,31 @@ public abstract class AbstractNioByteChannel extends AbstractNioChannel {
|
||||
}
|
||||
} else if (msg instanceof FileRegion) {
|
||||
FileRegion region = (FileRegion) msg;
|
||||
boolean done = region.transfered() >= region.count();
|
||||
boolean setOpWrite = false;
|
||||
boolean done = false;
|
||||
long flushedAmount = 0;
|
||||
if (writeSpinCount == -1) {
|
||||
writeSpinCount = config().getWriteSpinCount();
|
||||
}
|
||||
for (int i = writeSpinCount - 1; i >= 0; i --) {
|
||||
long localFlushedAmount = doWriteFileRegion(region);
|
||||
if (localFlushedAmount == 0) {
|
||||
setOpWrite = true;
|
||||
break;
|
||||
|
||||
if (!done) {
|
||||
long flushedAmount = 0;
|
||||
if (writeSpinCount == -1) {
|
||||
writeSpinCount = config().getWriteSpinCount();
|
||||
}
|
||||
|
||||
flushedAmount += localFlushedAmount;
|
||||
if (region.transfered() >= region.count()) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = writeSpinCount - 1; i >= 0; i--) {
|
||||
long localFlushedAmount = doWriteFileRegion(region);
|
||||
if (localFlushedAmount == 0) {
|
||||
setOpWrite = true;
|
||||
break;
|
||||
}
|
||||
|
||||
in.progress(flushedAmount);
|
||||
flushedAmount += localFlushedAmount;
|
||||
if (region.transfered() >= region.count()) {
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
in.progress(flushedAmount);
|
||||
}
|
||||
|
||||
if (done) {
|
||||
in.remove();
|
||||
|
Loading…
Reference in New Issue
Block a user