[ 
https://issues.apache.org/jira/browse/JCS-248?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18106325#comment-18106325
 ] 

Thomas Buffagni commented on JCS-248:
-------------------------------------

Pull request submitted: https://github.com/apache/commons-jcs/pull/415

The patch targets the current JCS 4 master branch and includes a regression 
test. The full Maven reactor completed successfully.

> ElementEventQueue.dispose() does not shut down its owned executor, leaking 
> threads across web application redeployments
> -----------------------------------------------------------------------------------------------------------------------
>
>                 Key: JCS-248
>                 URL: https://issues.apache.org/jira/browse/JCS-248
>             Project: Commons JCS
>          Issue Type: Bug
>          Components: Composite Cache
>    Affects Versions: jcs-3.2.1, jcs-4.0
>         Environment: Apache Commons JCS 3.2.1; Apache Tomcat 11.0.24; Eclipse 
> Temurin JDK 25; Spring web application packaged as a WAR; local 
> non-distributed cache.
>            Reporter: Thomas Buffagni
>            Priority: Major
>              Labels: thread-leak,, tomcat,, webapp-lifecycle
>             Fix For: jcs-4.0
>
>
> *How the issue was discovered*
> The issue was discovered while running a Tomcat web-application lifecycle 
> benchmark. The benchmark repeatedly performs the following sequence:
> 1. Deploy the Spring WAR.
> 2. Initialize and exercise the local JCS cache.
> 3. Stop the Spring application context and invoke JCS.shutdown().
> 4. Undeploy the WAR from Tomcat.
> 5. Deploy it again and repeat the sequence.
> During WAR undeployment, Tomcat reported that threads created by the web 
> application had not been stopped. The threads named in the warnings were 
> JCS-ElementEventQueue-* workers.
> Inspection of the JVM after undeployment confirmed that two 
> JCS-ElementEventQueue-* worker threads remained alive even though the 
> application had been stopped and JCS.shutdown() had been invoked.
> Repeating the deploy/undeploy cycle caused additional worker threads to 
> accumulate and produced further Tomcat thread-leak warnings. After five 
> lifecycle cycles, ten warnings had been recorded and the number of live 
> threads showed an estimated growth of 2.3 threads per cycle.
> This undeployment behavior led to the inspection of 
> ElementEventQueue.dispose() and to the identification of the executor 
> lifecycle problem described below.
> *Problem*
> ElementEventQueue creates its own executor by calling:
> ThreadPoolManager.getInstance().createPool(...)
> The returned executor is not registered in the ThreadPoolManager internal 
> pool maps. Consequently, ThreadPoolManager.dispose() cannot shut it down.
> ElementEventQueue.dispose() sets the destroyed flag, but the 
> queueProcessor.shutdownNow() call is commented out. When JCS is used inside a 
> Tomcat web application, the executor threads survive application undeployment.
> The issue was reproduced at runtime with JCS 3.2.1. Code inspection confirms 
> that the same lifecycle problem is present in the current JCS 4.0.0-SNAPSHOT 
> source.
> *Steps to reproduce*
> 1. Deploy a Spring WAR that configures and uses a local JCS cache.
> 2. Execute a workload that creates the ElementEventQueue workers.
> 3. Invoke JCS.shutdown() while stopping the Spring application context.
> 4. Undeploy the WAR from Tomcat.
> 5. Deploy the WAR again and repeat the lifecycle cycle.
> 6. Inspect the Tomcat logs and live JVM threads after each undeployment.
> *Actual result*
> Two additional JCS-ElementEventQueue-* threads remain alive after each 
> application lifecycle cycle.
> In a five-cycle deploy/workload/undeploy test with JCS 3.2.1, the unpatched 
> implementation produced:
> - 10 Tomcat thread-leak warnings
> - final thread counts of 39, 41, 43, 46, and 48
> - an estimated thread-count slope of +2.3 threads per cycle
> *Expected result*
> ElementEventQueue.dispose() should terminate the executor owned by the queue. 
> No JCS-ElementEventQueue-* worker should remain alive after JCS shutdown and 
> WAR undeployment.
> *Root cause*
> ElementEventQueue obtains a newly created and unregistered executor from 
> ThreadPoolManager.createPool(). Because the queue owns this executor, it must 
> also terminate it explicitly.
> *Proposed fix*
> Call queueProcessor.shutdownNow() during the first execution of 
> ElementEventQueue.dispose().
> A regression test verifies that:
> - the worker thread is running before disposal
> - the worker terminates after disposal
> - repeated calls to dispose() remain safe
> *Validation*
> The patched JCS 3.2.1 JAR was built from source, packaged inside the test 
> WAR, and tested through five complete Tomcat deploy/workload/undeploy cycles.
> *Results after the patch:*
> - 0 Tomcat thread-leak warnings
> - final thread counts of 38, 38, 37, 37, and 38
> - an estimated thread-count slope of -0.1 threads per cycle
> The corresponding focused regression test also passes against the JCS 4 
> source tree.
> A pull request containing the fix and regression test will be submitted after 
> this issue provides the JCS issue identifier.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to