From 204c5b647e81e3dd4b567896b97b0da91f3a09b6 Mon Sep 17 00:00:00 2001 From: markt Date: Fri, 1 Oct 2010 16:32:31 +0000 Subject: [PATCH] Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=49905 Prevent memory leak when using aysnc session replication git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1003572 13f79535-47bb-0310-9956-ffa450edef68 --- .../interceptors/MessageDispatch15Interceptor.java | 5 +- .../catalina/tribes/util/TcclThreadFactory.java | 66 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 java/org/apache/catalina/tribes/util/TcclThreadFactory.java diff --git a/java/org/apache/catalina/tribes/group/interceptors/MessageDispatch15Interceptor.java b/java/org/apache/catalina/tribes/group/interceptors/MessageDispatch15Interceptor.java index d819d66bf..fe1343209 100644 --- a/java/org/apache/catalina/tribes/group/interceptors/MessageDispatch15Interceptor.java +++ b/java/org/apache/catalina/tribes/group/interceptors/MessageDispatch15Interceptor.java @@ -24,6 +24,7 @@ import org.apache.catalina.tribes.ChannelMessage; import org.apache.catalina.tribes.Member; import org.apache.catalina.tribes.group.InterceptorPayload; import org.apache.catalina.tribes.transport.bio.util.LinkObject; +import org.apache.catalina.tribes.util.TcclThreadFactory; /** * @@ -80,7 +81,9 @@ public class MessageDispatch15Interceptor extends MessageDispatchInterceptor { @Override public void startQueue() { if ( run ) return; - executor = new ThreadPoolExecutor(maxSpareThreads,maxThreads,keepAliveTime,TimeUnit.MILLISECONDS,runnablequeue); + executor = new ThreadPoolExecutor(maxSpareThreads, maxThreads, + keepAliveTime, TimeUnit.MILLISECONDS, runnablequeue, + new TcclThreadFactory()); run = true; } diff --git a/java/org/apache/catalina/tribes/util/TcclThreadFactory.java b/java/org/apache/catalina/tribes/util/TcclThreadFactory.java new file mode 100644 index 000000000..a1959f930 --- /dev/null +++ b/java/org/apache/catalina/tribes/util/TcclThreadFactory.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.catalina.tribes.util; + +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * ThreadFactory implementation that creates threads with the thread context + * class loader set to the class loader that loaded this factory. It is intended + * to be used when tasks may be passed to executors when the web application + * class loader is set as the thread context class loader, such as in async + * session replication. + */ +public class TcclThreadFactory implements ThreadFactory { + + private static final AtomicInteger poolNumber = new AtomicInteger(1); + private static final boolean IS_SECURITY_ENABLED = + (System.getSecurityManager() != null); + + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public TcclThreadFactory() { + SecurityManager s = System.getSecurityManager(); + group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); + namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; + } + + @Override + public Thread newThread(Runnable r) { + final Thread t = new Thread(group, r, namePrefix + + threadNumber.getAndIncrement()); + + if (IS_SECURITY_ENABLED) { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + t.setContextClassLoader(this.getClass().getClassLoader()); + return null; + } + }); + } else { + t.setContextClassLoader(this.getClass().getClassLoader()); + } + return t; + } + +} -- 2.11.0