Skip to content

Commit

Permalink
Fix buffer leak in Http2ClientUpgradeCodecTest (#13175)
Browse files Browse the repository at this point in the history
Motivation:
Manually enabling leak detection reveals buffer leak in
Http2ClientUpgradeCodecTest#testUpgradeToHttp2ConnectionHandler (check stack below).

By default Http2ConnectionHandlerBuilder creates Http2ConnectionHandler with
the default gracefulShutdownTimeoutMillis (30s) (this is not the case for Http2FrameCodecBuilder
where gracefulShutdownTimeoutMillis has explicit value 0).

The test invokes channel.finishAndReleaseAll() which is expected to invoke close(),
however in case of a default gracefulShutdownTimeoutMillis, this scheduled closed will not happen
as channel.finishAndReleaseAll() will cancel all scheduled tasks.

```
12:26:44.677 [Cleaner-0] ERROR io.netty5.buffer.LoggingLeakCallback - LEAK: Object "buffer (256 bytes)" was not property closed before it was garbage collected. A life-cycle back-trace (if any) is attached as suppressed exceptions. See https://netty.io/wiki/reference-counted-objects.html for more information.
io.netty5.buffer.LoggingLeakCallback$LeakReport: Object life-cycle trace:
	Suppressed: io.netty5.buffer.internal.LifecycleTracer$Traceback: ALLOCATE (current acquires = 0) T-690834us.
		at io.netty5.buffer.internal.ResourceSupport.<init>(ResourceSupport.java:42) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.buffer.internal.AdaptableBuffer.<init>(AdaptableBuffer.java:28) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.buffer.bytebuffer.NioBuffer.<init>(NioBuffer.java:66) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.buffer.bytebuffer.ByteBufferMemoryManager.createBuffer(ByteBufferMemoryManager.java:85) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.buffer.bytebuffer.ByteBufferMemoryManager.allocateShared(ByteBufferMemoryManager.java:59) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.buffer.ManagedBufferAllocator.allocate(ManagedBufferAllocator.java:54) ~[netty5-buffer-5.0.0.Alpha6-SNAPSHOT.jar:5.0.0.Alpha6-SNAPSHOT]
		at io.netty5.handler.codec.http2.DefaultHttp2HeadersEncoder.<init>(DefaultHttp2HeadersEncoder.java:32) ~[classes/:?]
		at io.netty5.handler.codec.http2.DefaultHttp2HeadersEncoder.<init>(DefaultHttp2HeadersEncoder.java:39) ~[classes/:?]
		at io.netty5.handler.codec.http2.DefaultHttp2FrameWriter.<init>(DefaultHttp2FrameWriter.java:90) ~[classes/:?]
		at io.netty5.handler.codec.http2.AbstractHttp2ConnectionHandlerBuilder.buildFromConnection(AbstractHttp2ConnectionHandlerBuilder.java:541) ~[classes/:?]
		at io.netty5.handler.codec.http2.AbstractHttp2ConnectionHandlerBuilder.build(AbstractHttp2ConnectionHandlerBuilder.java:533) ~[classes/:?]
		at io.netty5.handler.codec.http2.Http2ConnectionHandlerBuilder.build(Http2ConnectionHandlerBuilder.java:113) ~[classes/:?]
		at io.netty5.handler.codec.http2.Http2ClientUpgradeCodecTest.testUpgradeToHttp2ConnectionHandler(Http2ClientUpgradeCodecTest.java:38) ~[test-classes/:?]
		at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727) ~[junit-platform-commons-1.9.0.jar:1.9.0]
		at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68) ~[junit-jupiter-engine-5.9.0.jar:5.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:185) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:194) ~[?:?]
		at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?]
		at java.util.concurrent.ForkJoinTask.awaitDone(ForkJoinTask.java:436) ~[?:?]
		at java.util.concurrent.ForkJoinTask.join(ForkJoinTask.java:670) ~[?:?]
		at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.joinConcurrentTasksInReverseOrderToEnableWorkStealing(ForkJoinPoolHierarchicalTestExecutorService.java:162) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:136) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141) ~[junit-platform-engine-1.9.0.jar:1.9.0]
		at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137) ~[junit-platform-engine-1.9.0.jar:1.9.0]
```

Modification:
- Fix leak in Http2ClientUpgradeCodecTest#testUpgradeToHttp2ConnectionHandler

Result:
No more leaks in Http2ClientUpgradeCodecTest#testUpgradeToHttp2ConnectionHandler.
  • Loading branch information
violetagg committed Feb 1, 2023
1 parent de52231 commit 727bebd
Showing 1 changed file with 1 addition and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Http2ClientUpgradeCodecTest {
@Test
public void testUpgradeToHttp2ConnectionHandler() throws Exception {
testUpgrade(new Http2ConnectionHandlerBuilder().server(false).frameListener(
new Http2FrameAdapter()).build(), null);
new Http2FrameAdapter()).gracefulShutdownTimeoutMillis(0).build(), null);
}

@Test
Expand Down

0 comments on commit 727bebd

Please sign in to comment.