diff --git a/java/org/apache/catalina/core/StandardThreadExecutor.java b/java/org/apache/catalina/core/StandardThreadExecutor.java index a30f29c..80f429d 100644 --- a/java/org/apache/catalina/core/StandardThreadExecutor.java +++ b/java/org/apache/catalina/core/StandardThreadExecutor.java @@ -18,6 +18,7 @@ package org.apache.catalina.core; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import org.apache.catalina.Executor; @@ -27,10 +28,11 @@ import org.apache.catalina.util.LifecycleMBeanBase; import org.apache.tomcat.util.threads.ResizableExecutor; import org.apache.tomcat.util.threads.TaskQueue; import org.apache.tomcat.util.threads.TaskThreadFactory; +import org.apache.tomcat.util.threads.ThreadCreator; import org.apache.tomcat.util.threads.ThreadPoolExecutor; public class StandardThreadExecutor extends LifecycleMBeanBase - implements Executor, ResizableExecutor { + implements Executor, ResizableExecutor, ThreadCreator { // ---------------------------------------------- Properties /** @@ -319,6 +321,10 @@ public class StandardThreadExecutor extends LifecycleMBeanBase return false; } + @Override + public ThreadFactory getThreadFactory() { + return executor.getThreadFactory(); + } @Override protected String getDomainInternal() { diff --git a/java/org/apache/tomcat/jni/SSL.java b/java/org/apache/tomcat/jni/SSL.java index b726a54..fb9fc16 100644 --- a/java/org/apache/tomcat/jni/SSL.java +++ b/java/org/apache/tomcat/jni/SSL.java @@ -388,4 +388,10 @@ public final class SSL { * @return true if all SSL_OP_* are supported by OpenSSL library. */ public static native boolean hasOp(int op); + + /** + * Cleanup thread specific data structures. This needs to be called after a thread + * has completed ssl operations. + */ + public static native void threadCleanup(); } diff --git a/java/org/apache/tomcat/util/net/AprEndpoint.java b/java/org/apache/tomcat/util/net/AprEndpoint.java index 74d813f..2edf673 100644 --- a/java/org/apache/tomcat/util/net/AprEndpoint.java +++ b/java/org/apache/tomcat/util/net/AprEndpoint.java @@ -29,6 +29,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import org.apache.juli.logging.Log; @@ -50,6 +51,8 @@ import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.net.AbstractEndpoint.Acceptor.AcceptorState; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.security.PrivilegedSetTccl; +import org.apache.tomcat.util.threads.TaskThreadFactory; +import org.apache.tomcat.util.threads.ThreadCreator; /** @@ -670,6 +673,14 @@ public class AprEndpoint extends AbstractEndpoint { createExecutor(); } + Executor executor = getExecutor(); + if (isSSLEnabled() && executor instanceof ThreadCreator) { + ThreadFactory tf = ((ThreadCreator) executor).getThreadFactory(); + if (tf instanceof TaskThreadFactory) { + ((TaskThreadFactory) tf).addCleanupTask(SSL_CLEANUP); + } + } + initializeConnectionLatch(); // Start poller thread @@ -1024,6 +1035,13 @@ public class AprEndpoint extends AbstractEndpoint { return log; } + private static final Runnable SSL_CLEANUP = new Runnable() { + @Override + public void run() { + SSL.threadCleanup(); + } + }; + // --------------------------------------------------- Acceptor Inner Class /** * The background thread that listens for incoming TCP/IP connections and diff --git a/java/org/apache/tomcat/util/threads/TaskThreadFactory.java b/java/org/apache/tomcat/util/threads/TaskThreadFactory.java index af63f11..12a4eb7 100644 --- a/java/org/apache/tomcat/util/threads/TaskThreadFactory.java +++ b/java/org/apache/tomcat/util/threads/TaskThreadFactory.java @@ -16,6 +16,8 @@ */ package org.apache.tomcat.util.threads; +import java.util.Collection; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** @@ -29,6 +31,8 @@ public class TaskThreadFactory implements ThreadFactory { private final String namePrefix; private final boolean daemon; private final int threadPriority; + private final Collection cleanupTasks = new CopyOnWriteArrayList(); + public TaskThreadFactory(String namePrefix, boolean daemon, int priority) { SecurityManager s = System.getSecurityManager(); group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); @@ -38,11 +42,36 @@ public class TaskThreadFactory implements ThreadFactory { } @Override - public Thread newThread(Runnable r) { - TaskThread t = new TaskThread(group, r, namePrefix + threadNumber.getAndIncrement()); + public Thread newThread(final Runnable r) { + Runnable wrapped = new Runnable() { + @Override + public void run() { + try { + r.run(); + } finally { + for (Runnable task : cleanupTasks) { + task.run(); + } + } + } + }; + TaskThread t = new TaskThread(group, wrapped, namePrefix + threadNumber.getAndIncrement()); t.setDaemon(daemon); t.setPriority(threadPriority); return t; } + public void addCleanupTask(Runnable task) { + synchronized (cleanupTasks) { + if (!cleanupTasks.contains(task)) { + cleanupTasks.add(task); + } + } + } + + public boolean removeCleanupTask(Runnable task) { + synchronized (cleanupTasks) { + return cleanupTasks.remove(task); + } + } } diff --git a/java/org/apache/tomcat/util/threads/ThreadCreator.java b/java/org/apache/tomcat/util/threads/ThreadCreator.java new file mode 100644 index 0000000..94270b5 --- /dev/null +++ b/java/org/apache/tomcat/util/threads/ThreadCreator.java @@ -0,0 +1,17 @@ +/* + * ======================================================================== + * + * Copyright (c) by Hitachi Data Systems, 2016. All rights reserved. + * + * ======================================================================== + */ +package org.apache.tomcat.util.threads; + +import java.util.concurrent.ThreadFactory; + +public interface ThreadCreator { + /** + * @return The {@link ThreadFactory} used by this instance + */ + ThreadFactory getThreadFactory(); +} diff --git a/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java b/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java index bc84ad3..1479783 100644 --- a/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java +++ b/java/org/apache/tomcat/util/threads/ThreadPoolExecutor.java @@ -34,7 +34,7 @@ import org.apache.tomcat.util.res.StringManager; * @author fhanik * */ -public class ThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor { +public class ThreadPoolExecutor extends java.util.concurrent.ThreadPoolExecutor implements ThreadCreator { /** * The string manager for this package. */