This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push: new 2c5e826 Align with 9.0.m and 10.0.x 2c5e826 is described below commit 2c5e826d33cdd7a97659e1a159688e8abc476579 Author: Mark Thomas <ma...@apache.org> AuthorDate: Mon Dec 7 17:56:06 2020 +0000 Align with 9.0.m and 10.0.x Adds support for skipMemoryLeakChecksOnJvmShutdown to Context --- java/org/apache/catalina/core/StandardContext.java | 16 ++++++++ java/org/apache/catalina/filters/CorsFilter.java | 21 +++------- .../catalina/filters/CsrfPreventionFilter.java | 2 +- .../org/apache/catalina/filters/ExpiresFilter.java | 6 +-- .../catalina/filters/RequestDumperFilter.java | 3 ++ .../catalina/filters/RestCsrfPreventionFilter.java | 3 +- .../apache/catalina/loader/JdbcLeakPrevention.java | 3 +- .../apache/catalina/loader/LocalStrings.properties | 2 + .../catalina/loader/LocalStrings_fr.properties | 2 + .../catalina/loader/LocalStrings_ja.properties | 2 + .../catalina/loader/LocalStrings_ko.properties | 2 + .../catalina/loader/LocalStrings_zh_CN.properties | 2 + .../catalina/loader/WebappClassLoaderBase.java | 45 ++++++++++++++++++---- webapps/docs/changelog.xml | 7 ++++ webapps/docs/config/context.xml | 7 ++++ 15 files changed, 93 insertions(+), 30 deletions(-) diff --git a/java/org/apache/catalina/core/StandardContext.java b/java/org/apache/catalina/core/StandardContext.java index db04227..b3673ec 100644 --- a/java/org/apache/catalina/core/StandardContext.java +++ b/java/org/apache/catalina/core/StandardContext.java @@ -753,6 +753,12 @@ public class StandardContext extends ContainerBase private boolean clearReferencesThreadLocals = true; /** + * Should Tomcat skip the memory leak checks when the web application is + * stopped as part of the process of shutting down the JVM? + */ + private boolean skipMemoryLeakChecksOnJvmShutdown = false; + + /** * Should the effective web.xml be logged when the context starts? */ private boolean logEffectiveWebXml = false; @@ -2739,6 +2745,16 @@ public class StandardContext extends ContainerBase } + public boolean getSkipMemoryLeakChecksOnJvmShutdown() { + return skipMemoryLeakChecksOnJvmShutdown; + } + + + public void setSkipMemoryLeakChecksOnJvmShutdown(boolean skipMemoryLeakChecksOnJvmShutdown) { + this.skipMemoryLeakChecksOnJvmShutdown = skipMemoryLeakChecksOnJvmShutdown; + } + + public Boolean getFailCtxIfServletStartFails() { return failCtxIfServletStartFails; } diff --git a/java/org/apache/catalina/filters/CorsFilter.java b/java/org/apache/catalina/filters/CorsFilter.java index 3a4613a..4f1091a 100644 --- a/java/org/apache/catalina/filters/CorsFilter.java +++ b/java/org/apache/catalina/filters/CorsFilter.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.net.URI; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -155,8 +156,6 @@ public class CorsFilter implements Filter { switch (requestType) { case SIMPLE: // Handles a Simple CORS request. - this.handleSimpleCORS(request, response, filterChain); - break; case ACTUAL: // Handles an Actual CORS request. this.handleSimpleCORS(request, response, filterChain); @@ -516,15 +515,6 @@ public class CorsFilter implements Filter { switch (corsRequestType) { case SIMPLE: - request.setAttribute( - CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST, - Boolean.TRUE); - request.setAttribute(CorsFilter.HTTP_REQUEST_ATTRIBUTE_ORIGIN, - request.getHeader(CorsFilter.REQUEST_HEADER_ORIGIN)); - request.setAttribute( - CorsFilter.HTTP_REQUEST_ATTRIBUTE_REQUEST_TYPE, - corsRequestType.name().toLowerCase(Locale.ENGLISH)); - break; case ACTUAL: request.setAttribute( CorsFilter.HTTP_REQUEST_ATTRIBUTE_IS_CORS_REQUEST, Boolean.TRUE); @@ -749,7 +739,7 @@ public class CorsFilter implements Filter { this.exposedHeaders.clear(); this.exposedHeaders.addAll(setExposedHeaders); - // For any value other then 'true' this will be false. + // For any value other than 'true' this will be false. this.supportsCredentials = Boolean.parseBoolean(supportsCredentials); if (this.supportsCredentials && this.anyOriginAllowed) { @@ -767,7 +757,7 @@ public class CorsFilter implements Filter { sm.getString("corsFilter.invalidPreflightMaxAge"), e); } - // For any value other then 'true' this will be false. + // For any value other than 'true' this will be false. this.decorateRequest = Boolean.parseBoolean(decorateRequest); } @@ -892,6 +882,7 @@ public class CorsFilter implements Filter { // -------------------------------------------------- CORS Response Headers + /** * The Access-Control-Allow-Origin header indicates whether a resource can * be shared based by returning the value of the Origin request header in @@ -1040,8 +1031,8 @@ public class CorsFilter implements Filter { * >http://www.w3.org/TR/cors/#terminology</a> */ public static final Collection<String> SIMPLE_HTTP_REQUEST_CONTENT_TYPE_VALUES = - new HashSet<>(Arrays.asList("application/x-www-form-urlencoded", - "multipart/form-data", "text/plain")); + Collections.unmodifiableSet(new HashSet<>(Arrays.asList( + "application/x-www-form-urlencoded", "multipart/form-data", "text/plain"))); // ------------------------------------------------ Configuration Defaults /** diff --git a/java/org/apache/catalina/filters/CsrfPreventionFilter.java b/java/org/apache/catalina/filters/CsrfPreventionFilter.java index 7be6ac0..fe7a27f 100644 --- a/java/org/apache/catalina/filters/CsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/CsrfPreventionFilter.java @@ -246,7 +246,7 @@ public class CsrfPreventionFilter extends CsrfPreventionFilterBase { return addNonce(super.encodeURL(url)); } - /** + /* * Return the specified URL with the nonce added to the query string. * * @param url URL to be modified diff --git a/java/org/apache/catalina/filters/ExpiresFilter.java b/java/org/apache/catalina/filters/ExpiresFilter.java index 6394985..af3e3c0 100644 --- a/java/org/apache/catalina/filters/ExpiresFilter.java +++ b/java/org/apache/catalina/filters/ExpiresFilter.java @@ -523,8 +523,8 @@ public class ExpiresFilter extends FilterBase { /** * Expiration configuration starting point. Either the time the - * html-page/servlet-response was served ({@link StartingPoint#ACCESS_TIME}) - * or the last time the html-page/servlet-response was modified ( + * HTML-page/servlet-response was served ({@link StartingPoint#ACCESS_TIME}) + * or the last time the HTML-page/servlet-response was modified ( * {@link StartingPoint#LAST_MODIFICATION_TIME}). */ protected enum StartingPoint { @@ -1104,7 +1104,7 @@ public class ExpiresFilter extends FilterBase { if (str == null || searchStr == null) { return false; } - return str.indexOf(searchStr) >= 0; + return str.contains(searchStr); } /** diff --git a/java/org/apache/catalina/filters/RequestDumperFilter.java b/java/org/apache/catalina/filters/RequestDumperFilter.java index d45d901..bcbe868 100644 --- a/java/org/apache/catalina/filters/RequestDumperFilter.java +++ b/java/org/apache/catalina/filters/RequestDumperFilter.java @@ -263,16 +263,19 @@ public class RequestDumperFilter implements Filter { return ts.dateString; } + @Override public void init(FilterConfig filterConfig) throws ServletException { // NOOP } + @Override public void destroy() { // NOOP } + private static final class Timestamp { private final Date date = new Date(0); private final SimpleDateFormat format = diff --git a/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java b/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java index 8587cf5..4fd6efc 100644 --- a/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java +++ b/java/org/apache/catalina/filters/RestCsrfPreventionFilter.java @@ -79,8 +79,7 @@ public class RestCsrfPreventionFilter extends CsrfPreventionFilterBase { NON_MODIFYING_METHOD, MODIFYING_METHOD } - private static final Pattern NON_MODIFYING_METHODS_PATTERN = Pattern - .compile("GET|HEAD|OPTIONS"); + private static final Pattern NON_MODIFYING_METHODS_PATTERN = Pattern.compile("GET|HEAD|OPTIONS"); private Set<String> pathsAcceptingParams = new HashSet<>(); diff --git a/java/org/apache/catalina/loader/JdbcLeakPrevention.java b/java/org/apache/catalina/loader/JdbcLeakPrevention.java index a6acd18..913fec5 100644 --- a/java/org/apache/catalina/loader/JdbcLeakPrevention.java +++ b/java/org/apache/catalina/loader/JdbcLeakPrevention.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Enumeration; import java.util.HashSet; import java.util.List; +import java.util.Set; /** * This class is loaded by {@link WebappClassLoaderBase} to enable it to @@ -52,7 +53,7 @@ public class JdbcLeakPrevention { * ensuring that both original drivers and any loaded as a result of the * side-effects are all de-registered. */ - HashSet<Driver> originalDrivers = new HashSet<>(); + Set<Driver> originalDrivers = new HashSet<>(); Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { originalDrivers.add(drivers.nextElement()); diff --git a/java/org/apache/catalina/loader/LocalStrings.properties b/java/org/apache/catalina/loader/LocalStrings.properties index 3ffd5c1..43a3bb4 100644 --- a/java/org/apache/catalina/loader/LocalStrings.properties +++ b/java/org/apache/catalina/loader/LocalStrings.properties @@ -44,6 +44,8 @@ webappClassLoader.loadedByThisOrChildFail=Failed to fully check the entries in a webappClassLoader.readError=Resource read error: Could not load [{0}]. webappClassLoader.removeTransformer=Removed class file transformer [{0}] from web application [{1}]. webappClassLoader.resourceModified=Resource [{0}] has been modified. The last modified time was [{1}] and is now [{2}] +webappClassLoader.restrictedPackage=Security violation, attempt to use restricted class [{0}] +webappClassLoader.securityException=Security exception trying to find class [{0}] in findClassInternal [{1}] webappClassLoader.stackTrace=The web application [{0}] appears to have started a thread named [{1}] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:{2} webappClassLoader.stackTraceRequestThread=The web application [{0}] is still processing a request that has yet to finish. This is very likely to create a memory leak. You can control the time allowed for requests to finish by using the unloadDelay attribute of the standard Context implementation. Stack trace of request processing thread:[{2}] webappClassLoader.stopThreadFail=Failed to terminate thread named [{0}] for web application [{1}] diff --git a/java/org/apache/catalina/loader/LocalStrings_fr.properties b/java/org/apache/catalina/loader/LocalStrings_fr.properties index 1bae2cc..46ba94a 100644 --- a/java/org/apache/catalina/loader/LocalStrings_fr.properties +++ b/java/org/apache/catalina/loader/LocalStrings_fr.properties @@ -44,6 +44,8 @@ webappClassLoader.loadedByThisOrChildFail=Impossible de vérifier complètement webappClassLoader.readError=Erreur lors de la lecture de la resource : impossible de charger [{0}]. webappClassLoader.removeTransformer=Enlevé le transformateur de fichiers de classe [{0}] de l''application web [{1}] webappClassLoader.resourceModified=La ressource [{0}] a été modifiée, la date de dernière modification était [{1}] et est désormais [{2}] +webappClassLoader.restrictedPackage=Violation de sécurité en essayant d''utiliser à une classe à accès restreint [{0}] +webappClassLoader.securityException=Exception de sécurité en essayant de trouver la classe [{0}] dans findClassInternal [{1}] webappClassLoader.stackTrace=L''application web [{0}] semble avoir démarré un thread nommé [{1}] mais ne l''a pas arrêté, ce qui va probablement créer une fuite de mémoire ; la trace du thread est : {2} webappClassLoader.stackTraceRequestThread=Une requête de l''application web [{0}] est toujours en cours, ce qui causera certainement une fuite de mémoire, vous pouvez contrôler le temps alloué en utilisant l''attribut unloadDelay de l''implémentation standard de Context ; trace du fil d’exécution de la requête : [{2}] webappClassLoader.stopThreadFail=Impossible de terminer le thread nommé [{0}] pour l''application [{1}] diff --git a/java/org/apache/catalina/loader/LocalStrings_ja.properties b/java/org/apache/catalina/loader/LocalStrings_ja.properties index cd3b15d..a3b99e7 100644 --- a/java/org/apache/catalina/loader/LocalStrings_ja.properties +++ b/java/org/apache/catalina/loader/LocalStrings_ja.properties @@ -43,6 +43,8 @@ webappClassLoader.loadedByThisOrChildFail=クラス [{0}] のインスタンス webappClassLoader.readError=リソース読み込みエラー: [{0}] が読み込めませんでした。 webappClassLoader.removeTransformer=クラスファイル変換器 [{0}] を Web アプリケーション [{1}] から削除しました。 webappClassLoader.resourceModified=リソース [{0}] は変更されています。直前の更新日時は [{1}]、最新の更新日時は [{2}] です。 +webappClassLoader.restrictedPackage=セキュリティー違反。制限されたクラス [{0}] を使おうとしました。 +webappClassLoader.securityException=indClassInternal [{1}]でクラス[{0}]を検索中のセキュリティ例外です webappClassLoader.stackTrace=Webアプリケーション[{0}]は[{1}]という名前のスレッドを開始したようですが、停止に失敗しました。 これはメモリリークを引き起こす可能性が非常に高いです。 スレッドのスタックトレース:{2} webappClassLoader.stackTraceRequestThread=Webアプリケーション[{0}]はまだ完了していないリクエストを処理しています。 これはメモリリークを引き起こす可能性が非常に高いです。 リクエストの終了時間は、StandardContext実装のunloadDelay属性を使用して制御できます。 陸絵鵜sと処理スレッドのスタックトレース:[{2}] webappClassLoader.stopThreadFail=Web アプリケーション [{1}] のスレッド [{0}] は終了できません。 diff --git a/java/org/apache/catalina/loader/LocalStrings_ko.properties b/java/org/apache/catalina/loader/LocalStrings_ko.properties index e1d315f..50153c9 100644 --- a/java/org/apache/catalina/loader/LocalStrings_ko.properties +++ b/java/org/apache/catalina/loader/LocalStrings_ko.properties @@ -44,6 +44,8 @@ webappClassLoader.loadedByThisOrChildFail=컨텍스트 [{1}]에서 잠재적 메 webappClassLoader.readError=리소스 읽기 오류 : [{0}]을(를) 로드할 수 없었습니다. webappClassLoader.removeTransformer=웹 애플리케이션 [{1}](으)로부터 클래스 파일 Transformer [{0}]을(를) 제거했습니다. webappClassLoader.resourceModified=리소스 [{0}]이(가) 변경된 적이 있습니다. 최종 변경 시간이 [{1}]이었는데, 이제 [{2}](으)로 바뀌었습니다. +webappClassLoader.restrictedPackage=보안 위반 행위: 제한된 클래스 [{0}]을(를) 사용하려 시도했습니다. +webappClassLoader.securityException=findClassInternal에서, 클래스 [{0}]을(를) 찾으려 시도 중 보안 예외 발생: [{1}] webappClassLoader.stackTrace=웹 애플리케이션 [{0}]이(가) [{1}](이)라는 이름의 쓰레드를 시작시킨 것으로 보이지만, 해당 쓰레드를 중지시키지 못했습니다. 이는 메모리 누수를 유발할 가능성이 큽니다. 해당 쓰레드의 스택 트레이스:{2} webappClassLoader.stackTraceRequestThread=웹 애플리케이션 [{0}]이(가) 여전히 완료되지 않은 요청을 처리하고 있습니다. 이는 메모리 누수를 유발할 가능성이 높습니다. 표준 컨텍스트 구현의 unloadDelay 속성을 이용하여, 요청 완료 허용 시간을 통제할 수 있습니다. 요청 처리 쓰레드의 스택 트레이스:[{2}] webappClassLoader.stopThreadFail=웹 애플리케이션 [{1}]을 위한, [{0}](이)라는 이름의 쓰레드를 종료시키지 못했습니다. diff --git a/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties b/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties index 1a43950..ace8b96 100644 --- a/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties +++ b/java/org/apache/catalina/loader/LocalStrings_zh_CN.properties @@ -43,6 +43,8 @@ webappClassLoader.loadedByThisOrChildFail=无法完全检查[{0}]实例中的条 webappClassLoader.readError=资源读取错误:不能加载 [{0}]. webappClassLoader.removeTransformer=已从web应用程序[{1}]中删除类文件转换器[{0}]。 webappClassLoader.resourceModified=资源[{0}]已被修改。上次修改时间是[{1}],现在是[{2}] +webappClassLoader.restrictedPackage=安全冲突,尝试使用受限类[{0}] +webappClassLoader.securityException=尝试在findClassInternal[{1}]中查找类[{0}]时出现安全异常 webappClassLoader.stackTrace=Web应用程序[{0}]似乎启动了一个名为[{1}]的线程,但未能停止它。这很可能会造成内存泄漏。线程的堆栈跟踪:[{2}] webappClassLoader.stackTraceRequestThread=web应用程序[{0}]仍在处理一个尚未完成的请求。这很可能会造成内存泄漏。您可以使用标准上下文实现的unloadDelay属性来控制请求完成所允许的时间。请求处理线程的堆栈跟踪:[{2}] webappClassLoader.stopThreadFail=为web应用程序[{1}]终止线程[{0}]失败 diff --git a/java/org/apache/catalina/loader/WebappClassLoaderBase.java b/java/org/apache/catalina/loader/WebappClassLoaderBase.java index 2451876..75629d9 100644 --- a/java/org/apache/catalina/loader/WebappClassLoaderBase.java +++ b/java/org/apache/catalina/loader/WebappClassLoaderBase.java @@ -192,8 +192,7 @@ public abstract class WebappClassLoaderBase extends URLClassLoader /** * The string manager for this package. */ - protected static final StringManager sm = - StringManager.getManager(Constants.Package); + protected static final StringManager sm = StringManager.getManager(WebappClassLoaderBase.class); // ----------------------------------------------------------- Constructors @@ -397,6 +396,12 @@ public abstract class WebappClassLoaderBase extends URLClassLoader private boolean clearReferencesThreadLocals = true; /** + * Should Tomcat skip the memory leak checks when the web application is + * stopped as part of the process of shutting down the JVM? + */ + private boolean skipMemoryLeakChecksOnJvmShutdown = false; + + /** * Holds the class file transformers decorating this class loader. The * CopyOnWriteArrayList is thread safe. It is expensive on writes, but * those should be rare. It is very fast on reads, since synchronization @@ -652,6 +657,16 @@ public abstract class WebappClassLoaderBase extends URLClassLoader } + public boolean getSkipMemoryLeakChecksOnJvmShutdown() { + return skipMemoryLeakChecksOnJvmShutdown; + } + + + public void setSkipMemoryLeakChecksOnJvmShutdown(boolean skipMemoryLeakChecksOnJvmShutdown) { + this.skipMemoryLeakChecksOnJvmShutdown = skipMemoryLeakChecksOnJvmShutdown; + } + + // ------------------------------------------------------- Reloader Methods /** @@ -855,8 +870,8 @@ public abstract class WebappClassLoaderBase extends URLClassLoader clazz = findClassInternal(name); } } catch(AccessControlException ace) { - log.warn("WebappClassLoader.findClassInternal(" + name - + ") security exception: " + ace.getMessage(), ace); + log.warn(sm.getString("webappClassLoader.securityException", name, + ace.getMessage()), ace); throw new ClassNotFoundException(name, ace); } catch (RuntimeException e) { if (log.isTraceEnabled()) @@ -867,8 +882,8 @@ public abstract class WebappClassLoaderBase extends URLClassLoader try { clazz = super.findClass(name); } catch(AccessControlException ace) { - log.warn("WebappClassLoader.findClassInternal(" + name - + ") security exception: " + ace.getMessage(), ace); + log.warn(sm.getString("webappClassLoader.securityException", name, + ace.getMessage()), ace); throw new ClassNotFoundException(name, ace); } catch (RuntimeException e) { if (log.isTraceEnabled()) @@ -1292,8 +1307,7 @@ public abstract class WebappClassLoaderBase extends URLClassLoader try { securityManager.checkPackageAccess(name.substring(0,i)); } catch (SecurityException se) { - String error = "Security Violation, attempt to use " + - "Restricted Class: " + name; + String error = sm.getString("webappClassLoader.restrictedPackage", name); log.info(error, se); throw new ClassNotFoundException(error, se); } @@ -1592,6 +1606,21 @@ public abstract class WebappClassLoaderBase extends URLClassLoader */ protected void clearReferences() { + // If the JVM is shutting down, skip the memory leak checks + if (skipMemoryLeakChecksOnJvmShutdown + && !resources.getContext().getParent().getState().isAvailable()) { + // During reloading / redeployment the parent is expected to be + // available. Parent is not available so this might be a JVM + // shutdown. + try { + Thread dummyHook = new Thread(); + Runtime.getRuntime().addShutdownHook(dummyHook); + Runtime.getRuntime().removeShutdownHook(dummyHook); + } catch (IllegalStateException ise) { + return; + } + } + // De-register any remaining JDBC drivers clearReferencesJdbc(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 35ed0a6..13f7913 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -107,6 +107,13 @@ <subsection name="Catalina"> <changelog> <fix> + <bug>50175</bug>: Add a new attribute to the standard context + implementation, <code>skipMemoryLeakChecksOnJvmShutdown</code>, that + allows the user to configure Tomcat to skip the memory leak checks + usually performed during web application stop if that stop is triggered + by a JVM shutdown. (markt) + </fix> + <fix> <bug>60781</bug>: Escape elements in the access log that need to be escaped for the access log to be parsed unambiguously. (fschumacher/markt) diff --git a/webapps/docs/config/context.xml b/webapps/docs/config/context.xml index 37802d4..0adb5e3 100644 --- a/webapps/docs/config/context.xml +++ b/webapps/docs/config/context.xml @@ -829,6 +829,13 @@ default value of <code>true</code> will be used.</p> </attribute> + <attribute name="skipMemoryLeakChecksOnJvmShutdown" required="false"> + <p>If <code>true</code>, Tomcat will not perform the usual memory leak + checks when the web application is stopped if that web application is + stopped as part of a JVM shutdown. If not specified, the default value + of <code>false</code> will be used.</p> + </attribute> + <attribute name="unloadDelay" required="false"> <p>Number of ms that the container will wait for servlets to unload. If not specified, the default value is <code>2000</code> ms.</p> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org