iloveeyjafjalla opened a new issue, #11456:
URL: https://github.com/apache/rocketmq/issues/11456

   ### Before Creating the Bug Report
   
   - [x] I have searched the [open 
issues](https://github.com/apache/rocketmq/issues) of this repository and 
believe that this is not a duplicate.
   - [x] This is a defect in Apache RocketMQ, not a usage question.
   - [x] I can reproduce this on the current `develop` branch.
   
   ### RocketMQ Version
   
   develop @ `57c2dc04f78cc7e73e6b8c9436ee0fff0d0f46c3` (the revision this was 
verified on)
   
   ### Describe the Bug
   
   `RemotingProtocolServer` schedules the expired-request cleanup in its 
constructor:
   
   ```java
   this.timerExecutor = ThreadUtils.newSingleThreadScheduledExecutor(
       new 
ThreadFactoryBuilder().setNameFormat("RemotingServerScheduler-%d").build()
   );
   this.timerExecutor.scheduleAtFixedRate(this::cleanExpireRequest, 100, 100, 
TimeUnit.MILLISECONDS);
   ```
   
   `ThreadFactoryBuilder` produces **non-daemon** threads, and `shutdown()` 
stops the eight remoting executors but not this one:
   
   ```java
   this.defaultRemotingServer.shutdown();
   this.remotingChannelManager.shutdown();
   this.sendMessageExecutor.shutdown();
   this.pullMessageExecutor.shutdown();
   this.heartbeatExecutor.shutdown();
   this.updateOffsetExecutor.shutdown();
   this.topicRouteExecutor.shutdown();
   this.defaultExecutor.shutdown();
   // timerExecutor is never stopped
   ```
   
   So a proxy whose remoting server has been shut down keeps a live thread 
running `cleanExpireRequest` every 100 ms against the stopped server, and the 
non-daemon thread keeps the JVM alive after the Spring context has closed 
instead of letting the process exit.
   
   This is the same shape as #11427: a service created in a constructor is 
started but not stopped by the owner's shutdown path.
   
   ### Steps to Reproduce
   
   1. Start the proxy and stop it again (or close its Spring context in a test).
   2. `jstack` shows the `RemotingServerScheduler-1` thread still alive after 
`RemotingProtocolServer.shutdown()` returned, and the process does not exit on 
its own.
   3. The added test shows the same point without a proxy: with the current 
code `verify(timerExecutor).shutdown()` fails with `Wanted but not invoked`.
   
   ### What Did You Expect to See?
   
   `shutdown()` stops the executor it scheduled in the constructor, like the 
eight remoting executors it already stops, so nothing of the server survives 
the shutdown.
   
   ### What Did You See Instead?
   
   The timer thread survives the shutdown, keeps running the 100 ms cleanup 
task, and keeps the JVM alive.
   
   ### Additional Context
   
   `#10806` reports a different problem in the same class (the cleanup loop 
swallows exceptions); this one is about the executor's lifecycle.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to