This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
commit 27c936a6ff85e54a7cc7a70ce7c15aba762b1fd8 Author: Luigi De Masi <ldem...@redhat.com> AuthorDate: Mon Nov 4 23:30:23 2019 +0100 CAMEL-14137 Thread leak in camel-jetty component if maxThreads or minThreads property is set --- .../camel/component/jetty/JettyHttpComponent.java | 12 ++++ .../component/jetty/JettyThreadPoolSizeTest.java | 72 ++++++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java index 22c2c85..cd7645d 100644 --- a/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java +++ b/components/camel-jetty-common/src/main/java/org/apache/camel/component/jetty/JettyHttpComponent.java @@ -134,6 +134,7 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements protected boolean useXForwardedForHeader; private Integer proxyPort; private boolean sendServerVersion = true; + private QueuedThreadPool _queuedThreadPool; public JettyHttpComponent() { } @@ -480,6 +481,15 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements this.removeServerMBean(connectorRef.server); //mbContainer.removeBean(connectorRef.connector); } + if (_queuedThreadPool !=null){ + try { + _queuedThreadPool.stop(); + }catch(Throwable t){ + _queuedThreadPool.destroy(); + }finally { + _queuedThreadPool=null; + } + } } } } @@ -1319,6 +1329,8 @@ public abstract class JettyHttpComponent extends HttpCommonComponent implements qtp.setMaxThreads(maxThreads.intValue()); } tp = qtp; + _queuedThreadPool=qtp; + } if (tp != null) { try { diff --git a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyThreadPoolSizeTest.java b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyThreadPoolSizeTest.java new file mode 100644 index 0000000..27aae78 --- /dev/null +++ b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/JettyThreadPoolSizeTest.java @@ -0,0 +1,72 @@ +package org.apache.camel.component.jetty; + +import org.apache.camel.builder.RouteBuilder; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Set; + +public class JettyThreadPoolSizeTest extends BaseJettyTest { + + + private static final Logger log = LoggerFactory.getLogger(JettyThreadPoolSizeTest.class); + + + private JettyHttpComponent jettyComponent; + + private RouteBuilder builder; + + @Test + public void threadPoolTest(){ + + + Set<Thread> threadSet = Thread.getAllStackTraces().keySet(); + long initialJettyThreadNumber = threadSet.stream().filter(thread -> thread.getName().contains("CamelJettyServer")).count(); + + log.info("initial Jetty thread number (expected 5): "+ initialJettyThreadNumber); + + context.stop(); + + Set<Thread> threadSetAfterStop = Thread.getAllStackTraces().keySet(); + long jettyThreadNumberAfterStop = threadSetAfterStop.stream().filter(thread -> thread.getName().contains("CamelJettyServer")).count(); + + log.info("Jetty thread number after stopping Camel Context: (expected 0): "+ jettyThreadNumberAfterStop); + + + jettyComponent = (JettyHttpComponent)context.getComponent("jetty"); + jettyComponent.setMinThreads(5); + jettyComponent.setMaxThreads(5); + + context.start(); + Set<Thread> threadSetAfterRestart = Thread.getAllStackTraces().keySet(); + long jettyThreadNumberAfterRestart = threadSetAfterRestart.stream().filter(thread -> thread.getName().contains("CamelJettyServer")).count(); + + log.info("Jetty thread number after starting Camel Context: (expected 5): "+ jettyThreadNumberAfterRestart); + + + assertEquals(5,initialJettyThreadNumber); + + assertEquals(0,jettyThreadNumberAfterStop); + + assertEquals(5,jettyThreadNumberAfterRestart); + } + + @Override + protected RouteBuilder createRouteBuilder() throws Exception { + + builder = new RouteBuilder() { + @Override + public void configure() throws Exception { + // setup the jetty component with the custom minThreads + jettyComponent = (JettyHttpComponent)context.getComponent("jetty"); + jettyComponent.setMinThreads(5); + jettyComponent.setMaxThreads(5); + + from("jetty://http://localhost:{{port}}/myserverWithCustomPoolSize").to("mock:result"); + } + }; + return builder; + } + +}