Fix for Issue #3308 related to slice missing retain
Motivations: It seems that slicing a buffer and using this slice to write to CTX will decrease the initial refCnt to 0, while the original buffer is not yet fully used (not empty). Modifications: As suggested in the ticket and tested, when the currentBuffer is sliced since it will still be used later on, the currentBuffer is retained. Add a test case for this issue. Result: The currentBuffer still has its correct refCnt when reaching the last write (not sliced) of 1 and therefore will be released correctly. The exception does no more occur. This fix should be applied to all branches >= 4.0.
This commit is contained in:
parent
8ed4807360
commit
85fecba770
@ -828,6 +828,7 @@ public class HttpPostRequestEncoder implements ChunkedInput<HttpContent> {
|
||||
int length = currentBuffer.readableBytes();
|
||||
if (length > HttpPostBodyUtil.chunkSize) {
|
||||
ByteBuf slice = currentBuffer.slice(currentBuffer.readerIndex(), HttpPostBodyUtil.chunkSize);
|
||||
currentBuffer.retain();
|
||||
currentBuffer.skipBytes(HttpPostBodyUtil.chunkSize);
|
||||
return slice;
|
||||
} else {
|
||||
|
@ -16,8 +16,10 @@
|
||||
package io.netty.handler.codec.http.multipart;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.SlicedByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpRequest;
|
||||
import io.netty.handler.codec.http.HttpContent;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
import io.netty.handler.codec.http.HttpVersion;
|
||||
import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder.EncoderMode;
|
||||
@ -26,6 +28,7 @@ import io.netty.util.internal.StringUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpHeaderNames.*;
|
||||
@ -187,6 +190,38 @@ public class HttpPostRequestEncoderTest {
|
||||
assertEquals(expected, content);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpPostRequestEncoderSlicedBuffer() throws Exception {
|
||||
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1,
|
||||
HttpMethod.POST, "http://localhost");
|
||||
|
||||
HttpPostRequestEncoder encoder = new HttpPostRequestEncoder(request, true);
|
||||
// add Form attribute
|
||||
encoder.addBodyAttribute("getform", "POST");
|
||||
encoder.addBodyAttribute("info", "first value");
|
||||
encoder.addBodyAttribute("secondinfo", "secondvalue a&");
|
||||
encoder.addBodyAttribute("thirdinfo", "short text");
|
||||
int length = 100000;
|
||||
char[] array = new char[length];
|
||||
Arrays.fill(array, 'a');
|
||||
String longText = new String(array);
|
||||
encoder.addBodyAttribute("fourthinfo", longText.substring(0, 7470));
|
||||
File file1 = new File(getClass().getResource("/file-01.txt").toURI());
|
||||
encoder.addBodyFileUpload("myfile", file1, "application/x-zip-compressed", false);
|
||||
encoder.finalizeRequest();
|
||||
while (! encoder.isEndOfInput()) {
|
||||
HttpContent httpContent = encoder.readChunk(null);
|
||||
if (httpContent.content() instanceof SlicedByteBuf) {
|
||||
assertEquals(2, httpContent.content().refCnt());
|
||||
} else {
|
||||
assertEquals(1, httpContent.content().refCnt());
|
||||
}
|
||||
httpContent.release();
|
||||
}
|
||||
encoder.cleanFiles();
|
||||
encoder.close();
|
||||
}
|
||||
|
||||
private static String getRequestBody(HttpPostRequestEncoder encoder) throws Exception {
|
||||
encoder.finalizeRequest();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user