Skip to content

Promises of shutdown EventExecutors may cause leaks #8007

@rkapsi

Description

@rkapsi

I noticed this when our application was shutting down and it's not critical for us but it could be a problem if EventExecutors are being torn down on some ongoing basis.

Promises of EventExecutors that have been shutdown will "lie" that values/exceptions were set successfully and there is no way for the caller to know that it actually failed.

Expected behavior

Actual behavior

Steps to reproduce

Minimal yet complete reproducer code (or URL to code)

public class EventExecutorTest {
  @Test
  public void notifyAfterShutdown() throws Exception {
    EventExecutor executor = new DefaultEventExecutor();
    try {
      ByteBuf data = Unpooled.buffer(0);
      try {
        assertEquals(1, data.refCnt());

        Promise<ByteBuf> promsie = executor.newPromise();
        executor.shutdownGracefully(0L, 0L, TimeUnit.MILLISECONDS).sync();

        if (!promsie.trySuccess(data)) {
          ReferenceCountUtil.release(data);
        }

        // Leaking because trySuccess(...) returned true. The same applies 
        // for the other Promise's setter methods.
        assertEquals(0, data.refCnt());
        
      } finally {
        ReferenceCountUtil.safeRelease(data);
      }
    } finally {
      executor.shutdownGracefully();
    }
  }
}
// This Exception is raised internally
java.util.concurrent.RejectedExecutionException: event executor terminated
	at io.netty.util.concurrent.SingleThreadEventExecutor.reject(SingleThreadEventExecutor.java:842) ~[netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.SingleThreadEventExecutor.offerTask(SingleThreadEventExecutor.java:328) ~[netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.SingleThreadEventExecutor.addTask(SingleThreadEventExecutor.java:321) ~[netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.SingleThreadEventExecutor.execute(SingleThreadEventExecutor.java:765) ~[netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.DefaultPromise.safeExecute(DefaultPromise.java:764) [netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:432) [netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:94) [netty-all-4.1.25.Final.jar:?]
	at io.netty.util.concurrent.EventExecutorTest.notifyAfterShutdown(EventExecutorTest.java:31) [test/:?]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_172]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_172]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_172]
	at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_172]
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:108) [testng-6.11.jar:?]
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:661) [testng-6.11.jar:?]
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:869) [testng-6.11.jar:?]
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1193) [testng-6.11.jar:?]
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126) [testng-6.11.jar:?]
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109) [testng-6.11.jar:?]
	at org.testng.TestRunner.privateRun(TestRunner.java:744) [testng-6.11.jar:?]
	at org.testng.TestRunner.run(TestRunner.java:602) [testng-6.11.jar:?]
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:380) [testng-6.11.jar:?]
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:375) [testng-6.11.jar:?]
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340) [testng-6.11.jar:?]
	at org.testng.SuiteRunner.run(SuiteRunner.java:289) [testng-6.11.jar:?]
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52) [testng-6.11.jar:?]
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86) [testng-6.11.jar:?]
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1301) [testng-6.11.jar:?]
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1226) [testng-6.11.jar:?]
	at org.testng.TestNG.runSuites(TestNG.java:1144) [testng-6.11.jar:?]
	at org.testng.TestNG.run(TestNG.java:1115) [testng-6.11.jar:?]
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114) [testng-remote.jar:?]
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251) [testng-remote.jar:?]
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77) [testng-remote.jar:?]
// Leaking...
FAILED: notifyAfterShutdown
java.lang.AssertionError: expected:<0> but was:<1>
	at org.testng.AssertJUnit.fail(AssertJUnit.java:59)
	at org.testng.AssertJUnit.failNotEquals(AssertJUnit.java:364)
	at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:80)
	at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:245)
	at org.testng.AssertJUnit.assertEquals(AssertJUnit.java:252)
	at io.netty.util.concurrent.EventExecutorTest.notifyAfterShutdown(EventExecutorTest.java:34)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:108)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:661)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:869)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1193)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:126)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:744)
	at org.testng.TestRunner.run(TestRunner.java:602)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:380)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:375)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
	at org.testng.SuiteRunner.run(SuiteRunner.java:289)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1301)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1226)
	at org.testng.TestNG.runSuites(TestNG.java:1144)
	at org.testng.TestNG.run(TestNG.java:1115)
	at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:114)
	at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
	at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

Netty version

4.1.25

JVM version (e.g. java -version)

OS version (e.g. uname -a)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions