Fix buffer leak introduced by #2462

Motivation:
Because of not correctly release a buffer before null out the reference a memory leak shows up.

Modifications:
Correct call buffer.release() before null out reference.

Result:
No more leak
This commit is contained in:
Norman Maurer 2014-05-06 10:03:24 +02:00
parent 1aca3863eb
commit e1becd2147
3 changed files with 50 additions and 36 deletions

View File

@ -81,7 +81,7 @@ public class SpdyHeaderBlockRawDecoder extends SpdyHeaderBlockDecoder {
if (cumulation.isReadable()) { if (cumulation.isReadable()) {
cumulation.discardReadBytes(); cumulation.discardReadBytes();
} else { } else {
cumulation = null; releaseBuffer();
} }
} }
} }

View File

@ -17,6 +17,8 @@ package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -42,9 +44,14 @@ public class SpdyHeaderBlockRawDecoderTest {
frame = new DefaultSpdyHeadersFrame(1); frame = new DefaultSpdyHeadersFrame(1);
} }
@After
public void tearDown() {
decoder.end();
}
@Test @Test
public void testEmptyHeaderBlock() throws Exception { public void testEmptyHeaderBlock() throws Exception {
ByteBuf headerBlock = Unpooled.EMPTY_BUFFER; ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.EMPTY_BUFFER);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
@ -55,7 +62,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testZeroNameValuePairs() throws Exception { public void testZeroNameValuePairs() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(4); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(0); headerBlock.writeInt(0);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
@ -67,7 +74,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testNegativeNameValuePairs() throws Exception { public void testNegativeNameValuePairs() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(4); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(-1); headerBlock.writeInt(-1);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
@ -78,7 +85,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testOneNameValuePair() throws Exception { public void testOneNameValuePair() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(21); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(21));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -97,7 +104,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMissingNameLength() throws Exception { public void testMissingNameLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(4); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
headerBlock.writeInt(1); headerBlock.writeInt(1);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
decoder.endHeaderBlock(frame); decoder.endHeaderBlock(frame);
@ -109,7 +116,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testZeroNameLength() throws Exception { public void testZeroNameLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(8); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(0); headerBlock.writeInt(0);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
@ -121,7 +128,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testNegativeNameLength() throws Exception { public void testNegativeNameLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(8); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(-1); headerBlock.writeInt(-1);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
@ -133,7 +140,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMissingName() throws Exception { public void testMissingName() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(8); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
decoder.decode(headerBlock, frame); decoder.decode(headerBlock, frame);
@ -146,7 +153,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testIllegalNameOnlyNull() throws Exception { public void testIllegalNameOnlyNull() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(18); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(18));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeByte(0); headerBlock.writeByte(0);
@ -161,7 +168,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMissingValueLength() throws Exception { public void testMissingValueLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(12); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(12));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -175,7 +182,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testZeroValueLength() throws Exception { public void testZeroValueLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(16); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(16));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -193,7 +200,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testNegativeValueLength() throws Exception { public void testNegativeValueLength() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(16); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(16));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -207,7 +214,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMissingValue() throws Exception { public void testMissingValue() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(16); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(16));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -222,7 +229,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testIllegalValueOnlyNull() throws Exception { public void testIllegalValueOnlyNull() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(17); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(17));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -237,7 +244,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testIllegalValueStartsWithNull() throws Exception { public void testIllegalValueStartsWithNull() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(22); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(22));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -253,7 +260,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testIllegalValueEndsWithNull() throws Exception { public void testIllegalValueEndsWithNull() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(22); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(22));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -269,7 +276,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMultipleValues() throws Exception { public void testMultipleValues() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(27); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(27));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -291,7 +298,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMultipleValuesEndsWithNull() throws Exception { public void testMultipleValuesEndsWithNull() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(28); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(28));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -312,7 +319,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testIllegalValueMultipleNulls() throws Exception { public void testIllegalValueMultipleNulls() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(28); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(28));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -331,7 +338,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMissingNextNameValuePair() throws Exception { public void testMissingNextNameValuePair() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(21); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(21));
headerBlock.writeInt(2); headerBlock.writeInt(2);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -350,7 +357,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMultipleNames() throws Exception { public void testMultipleNames() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(38); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(38));
headerBlock.writeInt(2); headerBlock.writeInt(2);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -372,7 +379,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testExtraData() throws Exception { public void testExtraData() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(22); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(22));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -391,7 +398,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testMultipleDecodes() throws Exception { public void testMultipleDecodes() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(21); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(21));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);
@ -415,14 +422,14 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testContinueAfterInvalidHeaders() throws Exception { public void testContinueAfterInvalidHeaders() throws Exception {
ByteBuf numHeaders = Unpooled.buffer(4); ByteBuf numHeaders = ReferenceCountUtil.releaseLater(Unpooled.buffer(4));
numHeaders.writeInt(1); numHeaders.writeInt(1);
ByteBuf nameBlock = Unpooled.buffer(8); ByteBuf nameBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8));
nameBlock.writeInt(4); nameBlock.writeInt(4);
nameBlock.writeBytes(nameBytes); nameBlock.writeBytes(nameBytes);
ByteBuf valueBlock = Unpooled.buffer(9); ByteBuf valueBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(9));
valueBlock.writeInt(5); valueBlock.writeInt(5);
valueBlock.writeBytes(valueBytes); valueBlock.writeBytes(valueBytes);
@ -443,7 +450,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testTruncatedHeaderName() throws Exception { public void testTruncatedHeaderName() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(maxHeaderSize + 18); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(maxHeaderSize + 18));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(maxHeaderSize + 1); headerBlock.writeInt(maxHeaderSize + 1);
for (int i = 0; i < maxHeaderSize + 1; i++) { for (int i = 0; i < maxHeaderSize + 1; i++) {
@ -462,7 +469,7 @@ public class SpdyHeaderBlockRawDecoderTest {
@Test @Test
public void testTruncatedHeaderValue() throws Exception { public void testTruncatedHeaderValue() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(maxHeaderSize + 13); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(maxHeaderSize + 13));
headerBlock.writeInt(1); headerBlock.writeInt(1);
headerBlock.writeInt(4); headerBlock.writeInt(4);
headerBlock.writeBytes(nameBytes); headerBlock.writeBytes(nameBytes);

View File

@ -17,6 +17,8 @@ package io.netty.handler.codec.spdy;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.util.ReferenceCountUtil;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -46,9 +48,14 @@ public class SpdyHeaderBlockZlibDecoderTest {
frame = new DefaultSpdyHeadersFrame(1); frame = new DefaultSpdyHeadersFrame(1);
} }
@After
public void tearDown() {
decoder.end();
}
@Test @Test
public void testHeaderBlock() throws Exception { public void testHeaderBlock() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(37); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(37));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x15); // little-endian length (21) headerBlock.writeByte(0x15); // little-endian length (21)
@ -74,7 +81,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test @Test
public void testHeaderBlockMultipleDecodes() throws Exception { public void testHeaderBlockMultipleDecodes() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(37); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(37));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x15); // little-endian length (21) headerBlock.writeByte(0x15); // little-endian length (21)
@ -105,7 +112,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test @Test
public void testLargeHeaderName() throws Exception { public void testLargeHeaderName() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(8220); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8220));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x0c); // little-endian length (8204) headerBlock.writeByte(0x0c); // little-endian length (8204)
@ -130,7 +137,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test @Test
public void testLargeHeaderValue() throws Exception { public void testLargeHeaderValue() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(8220); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(8220));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x0c); // little-endian length (8204) headerBlock.writeByte(0x0c); // little-endian length (8204)
@ -157,7 +164,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test(expected = SpdyProtocolException.class) @Test(expected = SpdyProtocolException.class)
public void testHeaderBlockExtraData() throws Exception { public void testHeaderBlockExtraData() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(37); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(37));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x15); // little-endian length (21) headerBlock.writeByte(0x15); // little-endian length (21)
@ -179,7 +186,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test(expected = SpdyProtocolException.class) @Test(expected = SpdyProtocolException.class)
public void testHeaderBlockInvalidDictionary() throws Exception { public void testHeaderBlockInvalidDictionary() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(7); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(7));
headerBlock.writeByte(0x78); headerBlock.writeByte(0x78);
headerBlock.writeByte(0x3f); headerBlock.writeByte(0x3f);
headerBlock.writeByte(0x01); // Unknown dictionary headerBlock.writeByte(0x01); // Unknown dictionary
@ -192,7 +199,7 @@ public class SpdyHeaderBlockZlibDecoderTest {
@Test(expected = SpdyProtocolException.class) @Test(expected = SpdyProtocolException.class)
public void testHeaderBlockInvalidDeflateBlock() throws Exception { public void testHeaderBlockInvalidDeflateBlock() throws Exception {
ByteBuf headerBlock = Unpooled.buffer(11); ByteBuf headerBlock = ReferenceCountUtil.releaseLater(Unpooled.buffer(11));
headerBlock.writeBytes(zlibHeader); headerBlock.writeBytes(zlibHeader);
headerBlock.writeByte(0); // Non-compressed block headerBlock.writeByte(0); // Non-compressed block
headerBlock.writeByte(0x00); // little-endian length (0) headerBlock.writeByte(0x00); // little-endian length (0)