[Bug 66792] unpacked war application for virtual host fails
https://bz.apache.org/bugzilla/show_bug.cgi?id=66792 Christopher Schultz changed: What|Removed |Added Resolution|--- |INVALID Status|NEW |RESOLVED --- Comment #1 from Christopher Schultz --- This is a file-permission issue in your environment, not a Tomcat bug. Please direct your question(s) to the Tomcat users mailing list for community support. -- You are receiving this mail because: You are the assignee for the bug. - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[Bug 66684] SSL HandShake failed when crlFile linked to an empty file
https://bz.apache.org/bugzilla/show_bug.cgi?id=66684 --- Comment #9 from Christopher Schultz --- (In reply to Mark Thomas from comment #8) > An empty file is not a valid CRL. See RFC 5280 for details. +1 It's not signed, so how could you trust it? -- You are receiving this mail because: You are the assignee for the bug. - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Update comment
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 b1a239056a Update comment b1a239056a is described below commit b1a239056a9643f3e8fd502909c66385678b8d51 Author: Mark Thomas AuthorDate: Wed Jul 26 17:19:22 2023 +0100 Update comment --- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index b32b9dbbfb..c6c219edf1 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -33,6 +33,7 @@ import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; import javax.servlet.http.WebConnection; @@ -1326,16 +1327,18 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH Stream pushStream; -// Synchronized since PUSH_PROMISE frames have to be sent in order. Once -// the stream has been created we need to ensure that the PUSH_PROMISE -// is sent before the next stream is created for a PUSH_PROMISE. -socketWrapper.getLock().lock(); +/* + * Uses SocketWrapper lock since PUSH_PROMISE frames have to be sent in order. Once the stream has been created + * we need to ensure that the PUSH_PROMISE is sent before the next stream is created for a PUSH_PROMISE. + */ +Lock lock = socketWrapper.getLock(); +lock.lock(); try { pushStream = createLocalStream(request); writeHeaders(associatedStream, pushStream.getIdAsInt(), request.getMimeHeaders(), false, Constants.DEFAULT_HEADERS_FRAME_SIZE); } finally { -socketWrapper.getLock().unlock(); +lock.unlock(); } pushStream.sentPushPromise(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Update comment
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 4db92d45e4 Update comment 4db92d45e4 is described below commit 4db92d45e445cb8b35869f42d8638419b2d71c93 Author: Mark Thomas AuthorDate: Wed Jul 26 17:19:22 2023 +0100 Update comment --- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 13 - 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index e653611498..0a8aa8c5d2 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -32,6 +32,7 @@ import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; import javax.servlet.http.WebConnection; @@ -1331,16 +1332,18 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH Stream pushStream; -// Synchronized since PUSH_PROMISE frames have to be sent in order. Once -// the stream has been created we need to ensure that the PUSH_PROMISE -// is sent before the next stream is created for a PUSH_PROMISE. -socketWrapper.getLock().lock(); +/* + * Uses SocketWrapper lock since PUSH_PROMISE frames have to be sent in order. Once the stream has been created + * we need to ensure that the PUSH_PROMISE is sent before the next stream is created for a PUSH_PROMISE. + */ +Lock lock = socketWrapper.getLock(); +lock.lock(); try { pushStream = createLocalStream(request); writeHeaders(associatedStream, pushStream.getIdAsInt(), request.getMimeHeaders(), false, Constants.DEFAULT_HEADERS_FRAME_SIZE); } finally { -socketWrapper.getLock().unlock(); +lock.unlock(); } pushStream.sentPushPromise(); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.1.x updated: Update comment
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new efbeae4f4a Update comment efbeae4f4a is described below commit efbeae4f4a86f0d9c49543a6a80ba0052259de14 Author: Mark Thomas AuthorDate: Wed Jul 26 17:19:22 2023 +0100 Update comment --- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index ec3e098c0d..811737bf83 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1338,9 +1338,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH Stream pushStream; -// Synchronized since PUSH_PROMISE frames have to be sent in order. Once -// the stream has been created we need to ensure that the PUSH_PROMISE -// is sent before the next stream is created for a PUSH_PROMISE. +/* + * Uses SocketWrapper lock since PUSH_PROMISE frames have to be sent in order. Once the stream has been created + * we need to ensure that the PUSH_PROMISE is sent before the next stream is created for a PUSH_PROMISE. + */ Lock lock = socketWrapper.getLock(); lock.lock(); try { - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated: Update comment
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/main by this push: new efea9d2641 Update comment efea9d2641 is described below commit efea9d264140ddc7fdcbe5c88060d4f65169b8d2 Author: Mark Thomas AuthorDate: Wed Jul 26 17:19:22 2023 +0100 Update comment --- java/org/apache/coyote/http2/Http2UpgradeHandler.java | 7 --- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2UpgradeHandler.java b/java/org/apache/coyote/http2/Http2UpgradeHandler.java index d890945452..73ddc28f3f 100644 --- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java @@ -1338,9 +1338,10 @@ class Http2UpgradeHandler extends AbstractStream implements InternalHttpUpgradeH Stream pushStream; -// Synchronized since PUSH_PROMISE frames have to be sent in order. Once -// the stream has been created we need to ensure that the PUSH_PROMISE -// is sent before the next stream is created for a PUSH_PROMISE. +/* + * Uses SocketWrapper lock since PUSH_PROMISE frames have to be sent in order. Once the stream has been created + * we need to ensure that the PUSH_PROMISE is sent before the next stream is created for a PUSH_PROMISE. + */ Lock lock = socketWrapper.getLock(); lock.lock(); try { - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Buildbot success in on tomcat-10.1.x
Build status: Build succeeded! Worker used: bb_worker2_ubuntu URL: https://ci2.apache.org/#builders/44/builds/879 Blamelist: Felix Schumacher , Mark Thomas Build Text: build successful Status Detected: restored build Build Source Stamp: [branch 10.1.x] 46e93b4ec6de63c1e63b4d8712c75adf000e0223 Steps: worker_preparation: 0 git: 0 shell: 0 shell_1: 0 shell_2: 0 shell_3: 0 shell_4: 0 shell_5: 0 compile: 1 shell_6: 0 shell_7: 0 shell_8: 0 shell_9: 0 Rsync docs to nightlies.apache.org: 0 shell_10: 0 Rsync RAT to nightlies.apache.org: 0 compile_1: 1 shell_11: 0 Rsync Logs to nightlies.apache.org: 0 -- ASF Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Catch NamingException instead of specialized sub-classes
This is an automated email from the ASF dual-hosted git repository. fschumacher 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 4b140ee40f Catch NamingException instead of specialized sub-classes 4b140ee40f is described below commit 4b140ee40f58373de28bf90eabec90fdcf53ef40 Author: Felix Schumacher AuthorDate: Thu Jul 20 11:14:19 2023 +0200 Catch NamingException instead of specialized sub-classes In Java 8 and up to 17 a closed connection is signaled with a NamingException and not a CommunicationException ora ServiceUnavailableException. Such a condition should lead to re-opening the LDAP connection. In Java 18 it is fixed by https://bugs.openjdk.org/browse/JDK-8273402 --- java/org/apache/catalina/realm/JNDIRealm.java | 10 +++--- webapps/docs/changelog.xml| 4 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java index 1f9690ab78..c55f075779 100644 --- a/java/org/apache/catalina/realm/JNDIRealm.java +++ b/java/org/apache/catalina/realm/JNDIRealm.java @@ -37,7 +37,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.naming.AuthenticationException; -import javax.naming.CommunicationException; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InvalidNameException; @@ -47,7 +46,6 @@ import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.PartialResultException; -import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; @@ -2372,7 +2370,13 @@ public class JNDIRealm extends RealmBase { // Authenticate the specified username if possible principal = getPrincipal(connection, username, gssCredential); -} catch (CommunicationException | ServiceUnavailableException e) { +} catch (NamingException e) { +/* While we would like to catch specialized exceptions like + * CommunicationException and ServiceUnavailableException, + * some network communication problems are reported as + * this general exception. This is fixed in Java 18 by + * https://bugs.openjdk.org/browse/JDK-8273402 + */ // log the exception so we know it's there. containerLog.info(sm.getString("jndiRealm.exception.retry"), e); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 0d5be9f071..f5cea73c49 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -116,6 +116,10 @@ presistence process, do not log a warning that null Principals are not serializable. Pull request 638 provided by tsryo. (markt) + +Catch NamingException in JNDIRealm#getPrincipal. +It is used in Java up to 17 to signal closed connections. (fschumacher) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Catch NamingException instead of specialized sub-classes
This is an automated email from the ASF dual-hosted git repository. fschumacher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 7e2cd05cee Catch NamingException instead of specialized sub-classes 7e2cd05cee is described below commit 7e2cd05cee8de346c3096437b5dda8da361dd47f Author: Felix Schumacher AuthorDate: Thu Jul 20 11:14:19 2023 +0200 Catch NamingException instead of specialized sub-classes In Java 8 and up to 17 a closed connection is signaled with a NamingException and not a CommunicationException ora ServiceUnavailableException. Such a condition should lead to re-opening the LDAP connection. In Java 18 it is fixed by https://bugs.openjdk.org/browse/JDK-8273402 --- java/org/apache/catalina/realm/JNDIRealm.java | 10 +++--- webapps/docs/changelog.xml| 4 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java index 619a704c99..a68f1a0db1 100644 --- a/java/org/apache/catalina/realm/JNDIRealm.java +++ b/java/org/apache/catalina/realm/JNDIRealm.java @@ -37,7 +37,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.naming.AuthenticationException; -import javax.naming.CommunicationException; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InvalidNameException; @@ -47,7 +46,6 @@ import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.PartialResultException; -import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; @@ -2356,7 +2354,13 @@ public class JNDIRealm extends RealmBase { // Authenticate the specified username if possible principal = getPrincipal(connection, username, gssCredential); -} catch (CommunicationException | ServiceUnavailableException e) { +} catch (NamingException e) { +/* While we would like to catch specialized exceptions like + * CommunicationException and ServiceUnavailableException, + * some network communication problems are reported as + * this general exception. This is fixed in Java 18 by + * https://bugs.openjdk.org/browse/JDK-8273402 + */ // log the exception so we know it's there. containerLog.info(sm.getString("jndiRealm.exception.retry"), e); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index f8b8f3f95e..b567b43f56 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -124,6 +124,10 @@ presistence process, do not log a warning that null Principals are not serializable. Pull request 638 provided by tsryo. (markt) + +Catch NamingException in JNDIRealm#getPrincipal. +It is used in Java up to 17 to signal closed connections. (fschumacher) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.1.x updated: Catch NamingException instead of specialized sub-classes
This is an automated email from the ASF dual-hosted git repository. fschumacher pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new 2a80e8e117 Catch NamingException instead of specialized sub-classes new 46e93b4ec6 Merge pull request #640 from FSchumacher/catch-naming-exception-in-getprincipal 2a80e8e117 is described below commit 2a80e8e117cf178aac23ce4deff04a49429ae1bd Author: Felix Schumacher AuthorDate: Thu Jul 20 11:14:19 2023 +0200 Catch NamingException instead of specialized sub-classes In Java 8 and up to 17 a closed connection is signaled with a NamingException and not a CommunicationException ora ServiceUnavailableException. Such a condition should lead to re-opening the LDAP connection. In Java 18 it is fixed by https://bugs.openjdk.org/browse/JDK-8273402 --- java/org/apache/catalina/realm/JNDIRealm.java | 10 +++--- webapps/docs/changelog.xml| 4 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/java/org/apache/catalina/realm/JNDIRealm.java b/java/org/apache/catalina/realm/JNDIRealm.java index 947eb1517f..f772c5acf6 100644 --- a/java/org/apache/catalina/realm/JNDIRealm.java +++ b/java/org/apache/catalina/realm/JNDIRealm.java @@ -37,7 +37,6 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.naming.AuthenticationException; -import javax.naming.CommunicationException; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InvalidNameException; @@ -47,7 +46,6 @@ import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.PartialResultException; -import javax.naming.ServiceUnavailableException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.DirContext; @@ -2355,7 +2353,13 @@ public class JNDIRealm extends RealmBase { // Authenticate the specified username if possible principal = getPrincipal(connection, username, gssCredential); -} catch (CommunicationException | ServiceUnavailableException e) { +} catch (NamingException e) { +/* While we would like to catch specialized exceptions like + * CommunicationException and ServiceUnavailableException, + * some network communication problems are reported as + * this general exception. This is fixed in Java 18 by + * https://bugs.openjdk.org/browse/JDK-8273402 + */ // log the exception so we know it's there. containerLog.info(sm.getString("jndiRealm.exception.retry"), e); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 246b17c9c3..a2631300b4 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -112,6 +112,10 @@ presistence process, do not log a warning that null Principals are not serializable. Pull request 638 provided by tsryo. (markt) + +Catch NamingException in JNDIRealm#getPrincipal. +It is used in Java up to 17 to signal closed connections. (fschumacher) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[GitHub] [tomcat] FSchumacher merged pull request #640: Catch NamingException instead of specialized sub-classes
FSchumacher merged PR #640: URL: https://github.com/apache/tomcat/pull/640 -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[GitHub] [tomcat] FSchumacher commented on pull request #640: Catch NamingException instead of specialized sub-classes
FSchumacher commented on PR #640: URL: https://github.com/apache/tomcat/pull/640#issuecomment-1651850085 > @FSchumacher, do you intend to backport it to 8.5 and 9.0? Yes, I will do that. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated (b11e591da4 -> 49c1fc65c2)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git from b11e591da4 Refactor to reduce pinning in HTTP/2 code when using virtual threads new fd625ae87d Remove debug logging. We have not seen the error repeat in 2 years. new 49c1fc65c2 Fix formatting The 2 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "add" were already present in the repository and have only been added to this reference. Summary of changes: .../apache/coyote/http2/TestCancelledUpload.java | 107 ++--- 1 file changed, 50 insertions(+), 57 deletions(-) - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 02/02: Fix formatting
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 commit 49c1fc65c2866ef3a5293d617e08ab99b24043f1 Author: Mark Thomas AuthorDate: Wed Jul 26 14:47:41 2023 +0100 Fix formatting --- test/org/apache/coyote/http2/TestCancelledUpload.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index ed59f6dee1..e5a1f34767 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,6 +19,7 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] 01/02: Remove debug logging. We have not seen the error repeat in 2 years.
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 commit fd625ae87da5f3228e1056ce4b47def5bd2965b4 Author: Mark Thomas AuthorDate: Wed Jul 26 14:43:10 2023 +0100 Remove debug logging. We have not seen the error repeat in 2 years. --- .../apache/coyote/http2/TestCancelledUpload.java | 108 ++--- 1 file changed, 50 insertions(+), 58 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index dacbb4e320..ed59f6dee1 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,9 +19,6 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.LogManager; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -39,71 +36,66 @@ public class TestCancelledUpload extends Http2TestBase { public void testCancelledRequest() throws Exception { http2Connect(); - LogManager.getLogManager().getLogger("org.apache.coyote.http2").setLevel(Level.ALL); -try { -http2Protocol.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); - -int bodySize = 8192; -int bodyCount = 20; +http2Protocol.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); -byte[] headersFrameHeader = new byte[9]; -ByteBuffer headersPayload = ByteBuffer.allocate(128); -byte[] dataFrameHeader = new byte[9]; -ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); -byte[] trailerFrameHeader = new byte[9]; -ByteBuffer trailerPayload = ByteBuffer.allocate(256); +int bodySize = 8192; +int bodyCount = 20; -buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, -trailerFrameHeader, trailerPayload, 3); +byte[] headersFrameHeader = new byte[9]; +ByteBuffer headersPayload = ByteBuffer.allocate(128); +byte[] dataFrameHeader = new byte[9]; +ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); +byte[] trailerFrameHeader = new byte[9]; +ByteBuffer trailerPayload = ByteBuffer.allocate(256); -// Write the headers -writeFrame(headersFrameHeader, headersPayload); -// Body -for (int i = 0; i < bodyCount; i++) { -writeFrame(dataFrameHeader, dataPayload); -} +buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, +trailerFrameHeader, trailerPayload, 3); -// Trailers -writeFrame(trailerFrameHeader, trailerPayload); - -// The Server will process the request on a separate thread to the -// incoming frames. -// The request processing thread will: -// - read up to 128 bytes of request body -// (and issue a window update for bytes read) -// - write a 403 response with no response body -// The connection processing thread will: -// - read the request body until the flow control window is exhausted -// - reset the stream if further DATA frames are received -parser.readFrame(); +// Write the headers +writeFrame(headersFrameHeader, headersPayload); +// Body +for (int i = 0; i < bodyCount; i++) { +writeFrame(dataFrameHeader, dataPayload); +} -// Check for reset and exit if found -if (checkReset()) { -return; -} +// Trailers +writeFrame(trailerFrameHeader, trailerPayload); + +// The Server will process the request on a separate thread to the +// incoming frames. +// The request processing thread will: +// - read up to 128 bytes of request body +// (and issue a window update for bytes read) +// - write a 403 response with no response body +// The connection processing thread will: +// - read the request body until the flow control window is exhausted +// - reset the stream if further DATA frames are received +parser.readFrame(); + +// Check for reset and exit if found +if (checkReset()) { +return; +} -// Not window update, not reset, must be the headers -Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[403]\n" + "3-Header-[content-length]-[0]\n" + -"3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n", output.getTrace()); -
[tomcat] branch 9.0.x updated: Fix formatting
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 2c39e4e6df Fix formatting 2c39e4e6df is described below commit 2c39e4e6df3bcc2a68c64c1fc1a823f04311adac Author: Mark Thomas AuthorDate: Wed Jul 26 14:47:17 2023 +0100 Fix formatting --- test/org/apache/coyote/http2/TestCancelledUpload.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index ed59f6dee1..e5a1f34767 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,6 +19,7 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; + import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Remove debug logging. We have not seen the error repeat in 2 years.
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 33d26832e4 Remove debug logging. We have not seen the error repeat in 2 years. 33d26832e4 is described below commit 33d26832e4e32f800dfb689058a1ada454c55116 Author: Mark Thomas AuthorDate: Wed Jul 26 14:43:10 2023 +0100 Remove debug logging. We have not seen the error repeat in 2 years. --- .../apache/coyote/http2/TestCancelledUpload.java | 108 ++--- 1 file changed, 50 insertions(+), 58 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index dacbb4e320..ed59f6dee1 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,9 +19,6 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.LogManager; - import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -39,71 +36,66 @@ public class TestCancelledUpload extends Http2TestBase { public void testCancelledRequest() throws Exception { http2Connect(); - LogManager.getLogManager().getLogger("org.apache.coyote.http2").setLevel(Level.ALL); -try { -http2Protocol.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); - -int bodySize = 8192; -int bodyCount = 20; +http2Protocol.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); -byte[] headersFrameHeader = new byte[9]; -ByteBuffer headersPayload = ByteBuffer.allocate(128); -byte[] dataFrameHeader = new byte[9]; -ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); -byte[] trailerFrameHeader = new byte[9]; -ByteBuffer trailerPayload = ByteBuffer.allocate(256); +int bodySize = 8192; +int bodyCount = 20; -buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, -trailerFrameHeader, trailerPayload, 3); +byte[] headersFrameHeader = new byte[9]; +ByteBuffer headersPayload = ByteBuffer.allocate(128); +byte[] dataFrameHeader = new byte[9]; +ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); +byte[] trailerFrameHeader = new byte[9]; +ByteBuffer trailerPayload = ByteBuffer.allocate(256); -// Write the headers -writeFrame(headersFrameHeader, headersPayload); -// Body -for (int i = 0; i < bodyCount; i++) { -writeFrame(dataFrameHeader, dataPayload); -} +buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, +trailerFrameHeader, trailerPayload, 3); -// Trailers -writeFrame(trailerFrameHeader, trailerPayload); - -// The Server will process the request on a separate thread to the -// incoming frames. -// The request processing thread will: -// - read up to 128 bytes of request body -// (and issue a window update for bytes read) -// - write a 403 response with no response body -// The connection processing thread will: -// - read the request body until the flow control window is exhausted -// - reset the stream if further DATA frames are received -parser.readFrame(); +// Write the headers +writeFrame(headersFrameHeader, headersPayload); +// Body +for (int i = 0; i < bodyCount; i++) { +writeFrame(dataFrameHeader, dataPayload); +} -// Check for reset and exit if found -if (checkReset()) { -return; -} +// Trailers +writeFrame(trailerFrameHeader, trailerPayload); + +// The Server will process the request on a separate thread to the +// incoming frames. +// The request processing thread will: +// - read up to 128 bytes of request body +// (and issue a window update for bytes read) +// - write a 403 response with no response body +// The connection processing thread will: +// - read the request body until the flow control window is exhausted +// - reset the stream if further DATA frames are received +parser.readFrame(); + +// Check for reset and exit if found +if (checkReset()) { +return; +} -// Not window update, not reset, must be the headers -Assert.assertEquals("3-HeadersStart\n" +
[tomcat] branch 10.1.x updated: Remove debug logging. We have not seen the error repeat in 2 years.
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new 0b4b2f8cd2 Remove debug logging. We have not seen the error repeat in 2 years. 0b4b2f8cd2 is described below commit 0b4b2f8cd24e349ca363c9c3db00eacd52c90237 Author: Mark Thomas AuthorDate: Wed Jul 26 14:41:59 2023 +0100 Remove debug logging. We have not seen the error repeat in 2 years. --- .../apache/coyote/http2/TestCancelledUpload.java | 112 ++--- 1 file changed, 52 insertions(+), 60 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index fbe1725c04..e49ea23e29 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,8 +19,6 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.LogManager; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -40,72 +38,66 @@ public class TestCancelledUpload extends Http2TestBase { public void testCancelledRequest() throws Exception { http2Connect(); - LogManager.getLogManager().getLogger("org.apache.coyote.http2").setLevel(Level.ALL); -try { -((AbstractHttp11Protocol) http2Protocol.getHttp11Protocol()) -.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); - -int bodySize = 8192; -int bodyCount = 20; - -byte[] headersFrameHeader = new byte[9]; -ByteBuffer headersPayload = ByteBuffer.allocate(128); -byte[] dataFrameHeader = new byte[9]; -ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); -byte[] trailerFrameHeader = new byte[9]; -ByteBuffer trailerPayload = ByteBuffer.allocate(256); - -buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, -trailerFrameHeader, trailerPayload, 3); - -// Write the headers -writeFrame(headersFrameHeader, headersPayload); -// Body -for (int i = 0; i < bodyCount; i++) { -writeFrame(dataFrameHeader, dataPayload); -} +((AbstractHttp11Protocol) http2Protocol.getHttp11Protocol()).setAllowedTrailerHeaders(TRAILER_HEADER_NAME); -// Trailers -writeFrame(trailerFrameHeader, trailerPayload); - -// The Server will process the request on a separate thread to the -// incoming frames. -// The request processing thread will: -// - read up to 128 bytes of request body -// (and issue a window update for bytes read) -// - write a 403 response with no response body -// The connection processing thread will: -// - read the request body until the flow control window is exhausted -// - reset the stream if further DATA frames are received -parser.readFrame(); +int bodySize = 8192; +int bodyCount = 20; -// Check for reset and exit if found -if (checkReset()) { -return; -} +byte[] headersFrameHeader = new byte[9]; +ByteBuffer headersPayload = ByteBuffer.allocate(128); +byte[] dataFrameHeader = new byte[9]; +ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); +byte[] trailerFrameHeader = new byte[9]; +ByteBuffer trailerPayload = ByteBuffer.allocate(256); -// Not window update, not reset, must be the headers -Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[403]\n" + "3-Header-[content-length]-[0]\n" + -"3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(); +buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, +trailerFrameHeader, trailerPayload, 3); -// Check for reset and exit if found -if (checkReset()) { -return; -} +// Write the headers +writeFrame(headersFrameHeader, headersPayload); +// Body +for (int i = 0; i < bodyCount; i++) { +writeFrame(dataFrameHeader, dataPayload); +} -// Not window update, not reset, must be the response body -Assert.assertEquals("3-Body-0\n" + "3-EndOfStream\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(); +// Trailers +writeFrame(trailerFram
[tomcat] branch main updated: Remove debug logging. We have not seen the error repeat in 2 years.
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/main by this push: new 8ecb62e5a5 Remove debug logging. We have not seen the error repeat in 2 years. 8ecb62e5a5 is described below commit 8ecb62e5a53c46504b0acedabbb60aac74543eb0 Author: Mark Thomas AuthorDate: Wed Jul 26 14:41:59 2023 +0100 Remove debug logging. We have not seen the error repeat in 2 years. --- .../apache/coyote/http2/TestCancelledUpload.java | 112 ++--- 1 file changed, 52 insertions(+), 60 deletions(-) diff --git a/test/org/apache/coyote/http2/TestCancelledUpload.java b/test/org/apache/coyote/http2/TestCancelledUpload.java index fbe1725c04..e49ea23e29 100644 --- a/test/org/apache/coyote/http2/TestCancelledUpload.java +++ b/test/org/apache/coyote/http2/TestCancelledUpload.java @@ -19,8 +19,6 @@ package org.apache.coyote.http2; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; -import java.util.logging.Level; -import java.util.logging.LogManager; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; @@ -40,72 +38,66 @@ public class TestCancelledUpload extends Http2TestBase { public void testCancelledRequest() throws Exception { http2Connect(); - LogManager.getLogManager().getLogger("org.apache.coyote.http2").setLevel(Level.ALL); -try { -((AbstractHttp11Protocol) http2Protocol.getHttp11Protocol()) -.setAllowedTrailerHeaders(TRAILER_HEADER_NAME); - -int bodySize = 8192; -int bodyCount = 20; - -byte[] headersFrameHeader = new byte[9]; -ByteBuffer headersPayload = ByteBuffer.allocate(128); -byte[] dataFrameHeader = new byte[9]; -ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); -byte[] trailerFrameHeader = new byte[9]; -ByteBuffer trailerPayload = ByteBuffer.allocate(256); - -buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, -trailerFrameHeader, trailerPayload, 3); - -// Write the headers -writeFrame(headersFrameHeader, headersPayload); -// Body -for (int i = 0; i < bodyCount; i++) { -writeFrame(dataFrameHeader, dataPayload); -} +((AbstractHttp11Protocol) http2Protocol.getHttp11Protocol()).setAllowedTrailerHeaders(TRAILER_HEADER_NAME); -// Trailers -writeFrame(trailerFrameHeader, trailerPayload); - -// The Server will process the request on a separate thread to the -// incoming frames. -// The request processing thread will: -// - read up to 128 bytes of request body -// (and issue a window update for bytes read) -// - write a 403 response with no response body -// The connection processing thread will: -// - read the request body until the flow control window is exhausted -// - reset the stream if further DATA frames are received -parser.readFrame(); +int bodySize = 8192; +int bodyCount = 20; -// Check for reset and exit if found -if (checkReset()) { -return; -} +byte[] headersFrameHeader = new byte[9]; +ByteBuffer headersPayload = ByteBuffer.allocate(128); +byte[] dataFrameHeader = new byte[9]; +ByteBuffer dataPayload = ByteBuffer.allocate(bodySize); +byte[] trailerFrameHeader = new byte[9]; +ByteBuffer trailerPayload = ByteBuffer.allocate(256); -// Not window update, not reset, must be the headers -Assert.assertEquals("3-HeadersStart\n" + "3-Header-[:status]-[403]\n" + "3-Header-[content-length]-[0]\n" + -"3-Header-[date]-[Wed, 11 Nov 2015 19:18:42 GMT]\n" + "3-HeadersEnd\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(); +buildPostRequest(headersFrameHeader, headersPayload, false, dataFrameHeader, dataPayload, null, +trailerFrameHeader, trailerPayload, 3); -// Check for reset and exit if found -if (checkReset()) { -return; -} +// Write the headers +writeFrame(headersFrameHeader, headersPayload); +// Body +for (int i = 0; i < bodyCount; i++) { +writeFrame(dataFrameHeader, dataPayload); +} -// Not window update, not reset, must be the response body -Assert.assertEquals("3-Body-0\n" + "3-EndOfStream\n", output.getTrace()); -output.clearTrace(); -parser.readFrame(); +// Trailers +writeFrame(trailerFrameHea
[tomcat] branch 8.5.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
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 b11e591da4 Refactor to reduce pinning in HTTP/2 code when using virtual threads b11e591da4 is described below commit b11e591da4e57c4d9520a91fc5f6024cb7be3278 Author: Mark Thomas AuthorDate: Wed Jul 26 14:12:50 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 90 +--- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 3d2628668a..8fb14d5b33 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -1147,6 +1147,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StandardStreamInputBuffer extends StreamInputBuffer { +private final Lock readStateLock = new ReentrantLock(); /* * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the * Stream (or the Request/Response) used by the application is processed in one thread but the connection is @@ -1332,7 +1333,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final boolean isReadyForRead() { ensureBuffersExist(); -synchronized (this) { +readStateLock.lock(); +try { if (available() > 0) { return true; } @@ -1342,21 +1344,33 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { } return false; +} finally { +readStateLock.unlock(); } } @Override -final synchronized boolean isRequestBodyFullyRead() { -return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +final boolean isRequestBodyFullyRead() { +readStateLock.lock(); +try { +return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +} finally { +readStateLock.unlock(); +} } @Override -public final synchronized int available() { -if (inBuffer == null) { -return 0; +public final int available() { +readStateLock.lock(); +try { +if (inBuffer == null) { +return 0; +} +return inBuffer.position(); +} finally { +readStateLock.unlock(); } -return inBuffer.position(); } @@ -1364,26 +1378,31 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { * Called after placing some data in the inBuffer. */ @Override -final synchronized void onDataAvailable() throws IOException { -if (closed) { -swallowUnread(); -} else if (readInterest) { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.dispatch")); -} -readInterest = false; -coyoteRequest.action(ActionCode.DISPATCH_READ, null); -// Always need to dispatch since this thread is processing -// the incoming connection and streams are processed on their -// own. -coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); -} else { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.signal")); -} -synchronized (inBuffer) { -inBuffer.notifyAll(); +final void onDataAvailable() throws IOException { +readStateLock.lock(); +try { +if (closed) { +swallowUnread(); +} else if (readInterest) { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.dispatch")); +} +readInterest = false; +coyoteRequest.action(ActionCode.DISPATCH_READ, null); +// Always need to dispatch since this thread is processing +// the incoming connection and streams are processed on their +// own. +coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); +} else { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.signal")); +
[tomcat] branch 9.0.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new e74bda808a Refactor to reduce pinning in HTTP/2 code when using virtual threads e74bda808a is described below commit e74bda808aa043b09790135f53d7de692cc3e1c3 Author: Mark Thomas AuthorDate: Wed Jul 26 14:38:37 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 90 +--- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index bce6c33559..915fda02ac 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -1153,6 +1153,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StandardStreamInputBuffer extends StreamInputBuffer { +private final Lock readStateLock = new ReentrantLock(); /* * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the * Stream (or the Request/Response) used by the application is processed in one thread but the connection is @@ -1263,7 +1264,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final boolean isReadyForRead() { ensureBuffersExist(); -synchronized (this) { +readStateLock.lock(); +try { if (available() > 0) { return true; } @@ -1273,21 +1275,33 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { } return false; +} finally { +readStateLock.unlock(); } } @Override -final synchronized boolean isRequestBodyFullyRead() { -return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +final boolean isRequestBodyFullyRead() { +readStateLock.lock(); +try { +return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +} finally { +readStateLock.unlock(); +} } @Override -public final synchronized int available() { -if (inBuffer == null) { -return 0; +public final int available() { +readStateLock.lock(); +try { +if (inBuffer == null) { +return 0; +} +return inBuffer.position(); +} finally { +readStateLock.unlock(); } -return inBuffer.position(); } @@ -1295,26 +1309,31 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { * Called after placing some data in the inBuffer. */ @Override -final synchronized void onDataAvailable() throws IOException { -if (closed) { -swallowUnread(); -} else if (readInterest) { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.dispatch")); -} -readInterest = false; -coyoteRequest.action(ActionCode.DISPATCH_READ, null); -// Always need to dispatch since this thread is processing -// the incoming connection and streams are processed on their -// own. -coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); -} else { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.signal")); -} -synchronized (inBuffer) { -inBuffer.notifyAll(); +final void onDataAvailable() throws IOException { +readStateLock.lock(); +try { +if (closed) { +swallowUnread(); +} else if (readInterest) { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.dispatch")); +} +readInterest = false; +coyoteRequest.action(ActionCode.DISPATCH_READ, null); +// Always need to dispatch since this thread is processing +// the incoming connection and streams are processed on their +// own. +coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); +} else { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.signal")); +
[tomcat] branch 10.1.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new 24b8501020 Refactor to reduce pinning in HTTP/2 code when using virtual threads 24b8501020 is described below commit 24b8501020eac62dbfe6957887aa8c2e1e0f803d Author: Mark Thomas AuthorDate: Wed Jul 26 14:38:37 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 90 +--- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 88056547fa..b0dd8ad844 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -1155,6 +1155,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StandardStreamInputBuffer extends StreamInputBuffer { +private final Lock readStateLock = new ReentrantLock(); /* * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the * Stream (or the Request/Response) used by the application is processed in one thread but the connection is @@ -1265,7 +1266,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final boolean isReadyForRead() { ensureBuffersExist(); -synchronized (this) { +readStateLock.lock(); +try { if (available() > 0) { return true; } @@ -1275,21 +1277,33 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { } return false; +} finally { +readStateLock.unlock(); } } @Override -final synchronized boolean isRequestBodyFullyRead() { -return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +final boolean isRequestBodyFullyRead() { +readStateLock.lock(); +try { +return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +} finally { +readStateLock.unlock(); +} } @Override -public final synchronized int available() { -if (inBuffer == null) { -return 0; +public final int available() { +readStateLock.lock(); +try { +if (inBuffer == null) { +return 0; +} +return inBuffer.position(); +} finally { +readStateLock.unlock(); } -return inBuffer.position(); } @@ -1297,26 +1311,31 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { * Called after placing some data in the inBuffer. */ @Override -final synchronized void onDataAvailable() throws IOException { -if (closed) { -swallowUnread(); -} else if (readInterest) { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.dispatch")); -} -readInterest = false; -coyoteRequest.action(ActionCode.DISPATCH_READ, null); -// Always need to dispatch since this thread is processing -// the incoming connection and streams are processed on their -// own. -coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); -} else { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.signal")); -} -synchronized (inBuffer) { -inBuffer.notifyAll(); +final void onDataAvailable() throws IOException { +readStateLock.lock(); +try { +if (closed) { +swallowUnread(); +} else if (readInterest) { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.dispatch")); +} +readInterest = false; +coyoteRequest.action(ActionCode.DISPATCH_READ, null); +// Always need to dispatch since this thread is processing +// the incoming connection and streams are processed on their +// own. +coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); +} else { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.signal")); +
[tomcat] branch main updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/main by this push: new 0338f2b113 Refactor to reduce pinning in HTTP/2 code when using virtual threads 0338f2b113 is described below commit 0338f2b113295482bacd9ef57264987cb4502f0e Author: Mark Thomas AuthorDate: Wed Jul 26 14:38:37 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 90 +--- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index d3fc2a7b4c..ff1f24ff12 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -1112,6 +1112,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StandardStreamInputBuffer extends StreamInputBuffer { +private final Lock readStateLock = new ReentrantLock(); /* * Two buffers are required to avoid various multi-threading issues. These issues arise from the fact that the * Stream (or the Request/Response) used by the application is processed in one thread but the connection is @@ -1222,7 +1223,8 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { final boolean isReadyForRead() { ensureBuffersExist(); -synchronized (this) { +readStateLock.lock(); +try { if (available() > 0) { return true; } @@ -1232,21 +1234,33 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { } return false; +} finally { +readStateLock.unlock(); } } @Override -final synchronized boolean isRequestBodyFullyRead() { -return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +final boolean isRequestBodyFullyRead() { +readStateLock.lock(); +try { +return (inBuffer == null || inBuffer.position() == 0) && isInputFinished(); +} finally { +readStateLock.unlock(); +} } @Override -public final synchronized int available() { -if (inBuffer == null) { -return 0; +public final int available() { +readStateLock.lock(); +try { +if (inBuffer == null) { +return 0; +} +return inBuffer.position(); +} finally { +readStateLock.unlock(); } -return inBuffer.position(); } @@ -1254,26 +1268,31 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { * Called after placing some data in the inBuffer. */ @Override -final synchronized void onDataAvailable() throws IOException { -if (closed) { -swallowUnread(); -} else if (readInterest) { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.dispatch")); -} -readInterest = false; -coyoteRequest.action(ActionCode.DISPATCH_READ, null); -// Always need to dispatch since this thread is processing -// the incoming connection and streams are processed on their -// own. -coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); -} else { -if (log.isDebugEnabled()) { -log.debug(sm.getString("stream.inputBuffer.signal")); -} -synchronized (inBuffer) { -inBuffer.notifyAll(); +final void onDataAvailable() throws IOException { +readStateLock.lock(); +try { +if (closed) { +swallowUnread(); +} else if (readInterest) { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.dispatch")); +} +readInterest = false; +coyoteRequest.action(ActionCode.DISPATCH_READ, null); +// Always need to dispatch since this thread is processing +// the incoming connection and streams are processed on their +// own. +coyoteRequest.action(ActionCode.DISPATCH_EXECUTE, null); +} else { +if (log.isDebugEnabled()) { +log.debug(sm.getString("stream.inputBuffer.signal")); +
[tomcat] branch 9.0.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 50f627546f Refactor to reduce pinning in HTTP/2 code when using virtual threads 50f627546f is described below commit 50f627546f085ae64aff4c3e4465d4cd797a685c Author: Mark Thomas AuthorDate: Wed Jul 26 13:23:39 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- .../apache/coyote/http2/Http2AsyncUpgradeHandler.java| 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java index 1b86d0da05..d9f69464f6 100644 --- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.WebConnection; @@ -44,9 +46,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // Ensures headers are generated and then written for one thread at a time. // Because of the compression used, headers need to be written to the // network in the same order they are generated. -private final Object headerWriteLock = new Object(); +private final Lock headerWriteLock = new ReentrantLock(); // Ensures thread triggers the stream reset is the first to send a RST frame -private final Object sendResetLock = new Object(); +private final Lock sendResetLock = new ReentrantLock(); private final AtomicReference error = new AtomicReference<>(); private final AtomicReference applicationIOE = new AtomicReference<>(); @@ -148,7 +150,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // may see out of order RST frames which may hard to follow if // the client is unaware the RST frames may be received out of // order. -synchronized (sendResetLock) { +sendResetLock.lock(); +try { if (state != null) { boolean active = state.isActive(); state.sendReset(); @@ -159,6 +162,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(rstFrame)); +} finally { +sendResetLock.unlock(); } handleAsyncException(); } @@ -191,7 +196,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { @Override void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize) throws IOException { -synchronized (headerWriteLock) { +headerWriteLock.lock(); +try { AsyncHeaderFrameBuffers headerFrameBuffers = (AsyncHeaderFrameBuffers) doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize); if (headerFrameBuffers != null) { @@ -200,6 +206,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { headerFrameBuffers.bufs.toArray(BYTEBUFFER_ARRAY)); handleAsyncException(); } +} finally { +headerWriteLock.unlock(); } if (endOfStream) { sentEndOfStream(stream); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.1.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new 905e6bbd47 Refactor to reduce pinning in HTTP/2 code when using virtual threads 905e6bbd47 is described below commit 905e6bbd47cc6d80d787ee833c5697f0a9f7f532 Author: Mark Thomas AuthorDate: Wed Jul 26 13:23:39 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- .../apache/coyote/http2/Http2AsyncUpgradeHandler.java| 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java index 9372037f3d..0a0868d477 100644 --- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import jakarta.servlet.http.WebConnection; @@ -44,9 +46,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // Ensures headers are generated and then written for one thread at a time. // Because of the compression used, headers need to be written to the // network in the same order they are generated. -private final Object headerWriteLock = new Object(); +private final Lock headerWriteLock = new ReentrantLock(); // Ensures thread triggers the stream reset is the first to send a RST frame -private final Object sendResetLock = new Object(); +private final Lock sendResetLock = new ReentrantLock(); private final AtomicReference error = new AtomicReference<>(); private final AtomicReference applicationIOE = new AtomicReference<>(); @@ -149,7 +151,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // may see out of order RST frames which may hard to follow if // the client is unaware the RST frames may be received out of // order. -synchronized (sendResetLock) { +sendResetLock.lock(); +try { if (state != null) { boolean active = state.isActive(); state.sendReset(); @@ -160,6 +163,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(rstFrame)); +} finally { +sendResetLock.unlock(); } handleAsyncException(); } @@ -192,7 +197,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { @Override void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize) throws IOException { -synchronized (headerWriteLock) { +headerWriteLock.lock(); +try { AsyncHeaderFrameBuffers headerFrameBuffers = (AsyncHeaderFrameBuffers) doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize); if (headerFrameBuffers != null) { @@ -201,6 +207,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { headerFrameBuffers.bufs.toArray(BYTEBUFFER_ARRAY)); handleAsyncException(); } +} finally { +headerWriteLock.unlock(); } if (endOfStream) { sentEndOfStream(stream); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/main by this push: new fa7f17b010 Refactor to reduce pinning in HTTP/2 code when using virtual threads fa7f17b010 is described below commit fa7f17b010057a1ea007cbd810c147baac95d000 Author: Mark Thomas AuthorDate: Wed Jul 26 13:23:39 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- .../apache/coyote/http2/Http2AsyncUpgradeHandler.java| 16 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java index 9372037f3d..0a0868d477 100644 --- a/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java +++ b/java/org/apache/coyote/http2/Http2AsyncUpgradeHandler.java @@ -26,6 +26,8 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import jakarta.servlet.http.WebConnection; @@ -44,9 +46,9 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // Ensures headers are generated and then written for one thread at a time. // Because of the compression used, headers need to be written to the // network in the same order they are generated. -private final Object headerWriteLock = new Object(); +private final Lock headerWriteLock = new ReentrantLock(); // Ensures thread triggers the stream reset is the first to send a RST frame -private final Object sendResetLock = new Object(); +private final Lock sendResetLock = new ReentrantLock(); private final AtomicReference error = new AtomicReference<>(); private final AtomicReference applicationIOE = new AtomicReference<>(); @@ -149,7 +151,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { // may see out of order RST frames which may hard to follow if // the client is unaware the RST frames may be received out of // order. -synchronized (sendResetLock) { +sendResetLock.lock(); +try { if (state != null) { boolean active = state.isActive(); state.sendReset(); @@ -160,6 +163,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { socketWrapper.write(BlockingMode.SEMI_BLOCK, protocol.getWriteTimeout(), TimeUnit.MILLISECONDS, null, SocketWrapperBase.COMPLETE_WRITE, errorCompletion, ByteBuffer.wrap(rstFrame)); +} finally { +sendResetLock.unlock(); } handleAsyncException(); } @@ -192,7 +197,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { @Override void writeHeaders(Stream stream, int pushedStreamId, MimeHeaders mimeHeaders, boolean endOfStream, int payloadSize) throws IOException { -synchronized (headerWriteLock) { +headerWriteLock.lock(); +try { AsyncHeaderFrameBuffers headerFrameBuffers = (AsyncHeaderFrameBuffers) doWriteHeaders(stream, pushedStreamId, mimeHeaders, endOfStream, payloadSize); if (headerFrameBuffers != null) { @@ -201,6 +207,8 @@ public class Http2AsyncUpgradeHandler extends Http2UpgradeHandler { headerFrameBuffers.bufs.toArray(BYTEBUFFER_ARRAY)); handleAsyncException(); } +} finally { +headerWriteLock.unlock(); } if (endOfStream) { sentEndOfStream(stream); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
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 259c615a76 Refactor to reduce pinning in HTTP/2 code when using virtual threads 259c615a76 is described below commit 259c615a764ce90a08e9a09c31f49379ce1cdb8b Author: Mark Thomas AuthorDate: Wed Jul 26 12:36:15 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 295 +-- 1 file changed, 164 insertions(+), 131 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 40ec7319ad..3d2628668a 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -26,6 +26,8 @@ import java.security.PrivilegedExceptionAction; import java.util.HashSet; import java.util.Locale; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import org.apache.coyote.ActionCode; import org.apache.coyote.CloseNowException; @@ -868,6 +870,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StreamOutputBuffer implements HttpOutputBuffer, WriteBuffer.Sink { +private final Lock writeLock = new ReentrantLock(); private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); private final WriteBuffer writeBuffer = new WriteBuffer(32 * 1024); // Flag that indicates that data was left over on a previous @@ -890,154 +893,179 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { */ @Deprecated @Override -public synchronized int doWrite(ByteChunk chunk) throws IOException { -if (closed) { -throw new IllegalStateException(sm.getString("stream.closed", getConnectionId(), getIdentifier())); -} -if (!coyoteResponse.isCommitted()) { -coyoteResponse.sendHeaders(); -} -int len = chunk.getLength(); -int offset = 0; -while (len > 0) { -int thisTime = Math.min(buffer.remaining(), len); -buffer.put(chunk.getBytes(), chunk.getOffset() + offset, thisTime); -offset += thisTime; -len -= thisTime; -if (len > 0 && !buffer.hasRemaining()) { -// Only flush if we have more data to write and the buffer -// is full -if (flush(true, coyoteResponse.getWriteListener() == null)) { -break; -} +public int doWrite(ByteChunk chunk) throws IOException { +writeLock.lock(); +try { +if (closed) { +throw new IllegalStateException(sm.getString("stream.closed", getConnectionId(), getIdentifier())); } -} -written += offset; -return offset; -} - -@Override -public final synchronized int doWrite(ByteBuffer chunk) throws IOException { -if (closed) { -throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); -} -int totalThisTime = 0; -if (writeBuffer.isEmpty()) { -int chunkLimit = chunk.limit(); -while (chunk.remaining() > 0) { -int thisTime = Math.min(buffer.remaining(), chunk.remaining()); -chunk.limit(chunk.position() + thisTime); -buffer.put(chunk); -chunk.limit(chunkLimit); -totalThisTime += thisTime; -if (chunk.remaining() > 0 && !buffer.hasRemaining()) { +if (!coyoteResponse.isCommitted()) { +coyoteResponse.sendHeaders(); +} +int len = chunk.getLength(); +int offset = 0; +while (len > 0) { +int thisTime = Math.min(buffer.remaining(), len); +buffer.put(chunk.getBytes(), chunk.getOffset() + offset, thisTime); +offset += thisTime; +len -= thisTime; +if (len > 0 && !buffer.hasRemaining()) { // Only flush if we have more data to write and the buffer // is full if (flush(true, coyoteResponse.getWriteListener() == null)) { -totalThisTime = chunk.remaining(); -writeBuffer.add(chunk); -dataLeft = true; break; } }
[GitHub] [tomcat] jfclere commented on pull request #641: Add DESTROYED state (if DESTROYED we are already STOPPED).
jfclere commented on PR #641: URL: https://github.com/apache/tomcat/pull/641#issuecomment-1651668981 @markt-asf there is something weird while removing the war file and letting Tomcat undeploying the webapp, randomly Tomcat seems to reject the connection of the shutdown port: java.net.ConnectException: Connection refused I created 200 war files put them webapps and wait until they are started and then remove the war files and try to stop Tomcat -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.1.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new d48c941249 Refactor to reduce pinning in HTTP/2 code when using virtual threads d48c941249 is described below commit d48c941249d51dd486735321b84a734b5de06af0 Author: Mark Thomas AuthorDate: Wed Jul 26 12:36:15 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 244 +-- 1 file changed, 136 insertions(+), 108 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 25b10d3391..88056547fa 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -28,6 +28,8 @@ import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import org.apache.coyote.ActionCode; @@ -913,6 +915,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StreamOutputBuffer implements HttpOutputBuffer, WriteBuffer.Sink { +private final Lock writeLock = new ReentrantLock(); private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); private final WriteBuffer writeBuffer = new WriteBuffer(32 * 1024); // Flag that indicates that data was left over on a previous @@ -931,125 +934,145 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { */ @Override -public final synchronized int doWrite(ByteBuffer chunk) throws IOException { -if (closed) { -throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); -} -// chunk is always fully written -int result = chunk.remaining(); -if (writeBuffer.isEmpty()) { -int chunkLimit = chunk.limit(); -while (chunk.remaining() > 0) { -int thisTime = Math.min(buffer.remaining(), chunk.remaining()); -chunk.limit(chunk.position() + thisTime); -buffer.put(chunk); -chunk.limit(chunkLimit); -if (chunk.remaining() > 0 && !buffer.hasRemaining()) { -// Only flush if we have more data to write and the buffer -// is full -if (flush(true, coyoteResponse.getWriteListener() == null)) { -writeBuffer.add(chunk); -dataLeft = true; -break; +public final int doWrite(ByteBuffer chunk) throws IOException { +writeLock.lock(); +try { +if (closed) { +throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); +} +// chunk is always fully written +int result = chunk.remaining(); +if (writeBuffer.isEmpty()) { +int chunkLimit = chunk.limit(); +while (chunk.remaining() > 0) { +int thisTime = Math.min(buffer.remaining(), chunk.remaining()); +chunk.limit(chunk.position() + thisTime); +buffer.put(chunk); +chunk.limit(chunkLimit); +if (chunk.remaining() > 0 && !buffer.hasRemaining()) { +// Only flush if we have more data to write and the buffer +// is full +if (flush(true, coyoteResponse.getWriteListener() == null)) { +writeBuffer.add(chunk); +dataLeft = true; +break; +} } } +} else { +writeBuffer.add(chunk); } -} else { -writeBuffer.add(chunk); +written += result; +return result; +} finally { +writeLock.unlock(); } -written += result; -return result; } -final synchronized boolean flush(boolean block) throws IOException { -/* - * Need to ensure that there is exactly one call to flush even when there is no data to write. Too few calls - * (i.e. zero) and the end of stream message is not sent for a completed asynchronous write. Too many calls - * and the end of stream message is sent too soon and t
[tomcat] branch main updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/main by this push: new 36e8fd9033 Refactor to reduce pinning in HTTP/2 code when using virtual threads 36e8fd9033 is described below commit 36e8fd9033ccc26e63667e6a75a6b213df9cfe9c Author: Mark Thomas AuthorDate: Wed Jul 26 12:36:15 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 244 +-- 1 file changed, 136 insertions(+), 108 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index ffd8e47a8d..d3fc2a7b4c 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -25,6 +25,8 @@ import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import org.apache.coyote.ActionCode; @@ -870,6 +872,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StreamOutputBuffer implements HttpOutputBuffer, WriteBuffer.Sink { +private final Lock writeLock = new ReentrantLock(); private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); private final WriteBuffer writeBuffer = new WriteBuffer(32 * 1024); // Flag that indicates that data was left over on a previous @@ -888,125 +891,145 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { */ @Override -public final synchronized int doWrite(ByteBuffer chunk) throws IOException { -if (closed) { -throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); -} -// chunk is always fully written -int result = chunk.remaining(); -if (writeBuffer.isEmpty()) { -int chunkLimit = chunk.limit(); -while (chunk.remaining() > 0) { -int thisTime = Math.min(buffer.remaining(), chunk.remaining()); -chunk.limit(chunk.position() + thisTime); -buffer.put(chunk); -chunk.limit(chunkLimit); -if (chunk.remaining() > 0 && !buffer.hasRemaining()) { -// Only flush if we have more data to write and the buffer -// is full -if (flush(true, coyoteResponse.getWriteListener() == null)) { -writeBuffer.add(chunk); -dataLeft = true; -break; +public final int doWrite(ByteBuffer chunk) throws IOException { +writeLock.lock(); +try { +if (closed) { +throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); +} +// chunk is always fully written +int result = chunk.remaining(); +if (writeBuffer.isEmpty()) { +int chunkLimit = chunk.limit(); +while (chunk.remaining() > 0) { +int thisTime = Math.min(buffer.remaining(), chunk.remaining()); +chunk.limit(chunk.position() + thisTime); +buffer.put(chunk); +chunk.limit(chunkLimit); +if (chunk.remaining() > 0 && !buffer.hasRemaining()) { +// Only flush if we have more data to write and the buffer +// is full +if (flush(true, coyoteResponse.getWriteListener() == null)) { +writeBuffer.add(chunk); +dataLeft = true; +break; +} } } +} else { +writeBuffer.add(chunk); } -} else { -writeBuffer.add(chunk); +written += result; +return result; +} finally { +writeLock.unlock(); } -written += result; -return result; } -final synchronized boolean flush(boolean block) throws IOException { -/* - * Need to ensure that there is exactly one call to flush even when there is no data to write. Too few calls - * (i.e. zero) and the end of stream message is not sent for a completed asynchronous write. Too many calls - * and the end of stream message is sent too soon and trail
[tomcat] branch 9.0.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new acf7bc0d20 Refactor to reduce pinning in HTTP/2 code when using virtual threads acf7bc0d20 is described below commit acf7bc0d20954f809cf2fb7a13afb6372d82f1f4 Author: Mark Thomas AuthorDate: Wed Jul 26 12:36:15 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/Stream.java | 244 +-- 1 file changed, 136 insertions(+), 108 deletions(-) diff --git a/java/org/apache/coyote/http2/Stream.java b/java/org/apache/coyote/http2/Stream.java index 4a770b54e4..bce6c33559 100644 --- a/java/org/apache/coyote/http2/Stream.java +++ b/java/org/apache/coyote/http2/Stream.java @@ -28,6 +28,8 @@ import java.util.HashSet; import java.util.Locale; import java.util.Map; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Supplier; import org.apache.coyote.ActionCode; @@ -911,6 +913,7 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { class StreamOutputBuffer implements HttpOutputBuffer, WriteBuffer.Sink { +private final Lock writeLock = new ReentrantLock(); private final ByteBuffer buffer = ByteBuffer.allocate(8 * 1024); private final WriteBuffer writeBuffer = new WriteBuffer(32 * 1024); // Flag that indicates that data was left over on a previous @@ -929,125 +932,145 @@ class Stream extends AbstractNonZeroStream implements HeaderEmitter { */ @Override -public final synchronized int doWrite(ByteBuffer chunk) throws IOException { -if (closed) { -throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); -} -// chunk is always fully written -int result = chunk.remaining(); -if (writeBuffer.isEmpty()) { -int chunkLimit = chunk.limit(); -while (chunk.remaining() > 0) { -int thisTime = Math.min(buffer.remaining(), chunk.remaining()); -chunk.limit(chunk.position() + thisTime); -buffer.put(chunk); -chunk.limit(chunkLimit); -if (chunk.remaining() > 0 && !buffer.hasRemaining()) { -// Only flush if we have more data to write and the buffer -// is full -if (flush(true, coyoteResponse.getWriteListener() == null)) { -writeBuffer.add(chunk); -dataLeft = true; -break; +public final int doWrite(ByteBuffer chunk) throws IOException { +writeLock.lock(); +try { +if (closed) { +throw new IOException(sm.getString("stream.closed", getConnectionId(), getIdAsString())); +} +// chunk is always fully written +int result = chunk.remaining(); +if (writeBuffer.isEmpty()) { +int chunkLimit = chunk.limit(); +while (chunk.remaining() > 0) { +int thisTime = Math.min(buffer.remaining(), chunk.remaining()); +chunk.limit(chunk.position() + thisTime); +buffer.put(chunk); +chunk.limit(chunkLimit); +if (chunk.remaining() > 0 && !buffer.hasRemaining()) { +// Only flush if we have more data to write and the buffer +// is full +if (flush(true, coyoteResponse.getWriteListener() == null)) { +writeBuffer.add(chunk); +dataLeft = true; +break; +} } } +} else { +writeBuffer.add(chunk); } -} else { -writeBuffer.add(chunk); +written += result; +return result; +} finally { +writeLock.unlock(); } -written += result; -return result; } -final synchronized boolean flush(boolean block) throws IOException { -/* - * Need to ensure that there is exactly one call to flush even when there is no data to write. Too few calls - * (i.e. zero) and the end of stream message is not sent for a completed asynchronous write. Too many calls - * and the end of stream message is sent too soon and tra
Buildbot failure in on tomcat-10.1.x
Build status: BUILD FAILED: failed Snapshot deployed to ASF Maven snapshot repository (failure) Worker used: bb_worker2_ubuntu URL: https://ci2.apache.org/#builders/44/builds/878 Blamelist: Mark Thomas Build Text: failed Snapshot deployed to ASF Maven snapshot repository (failure) Status Detected: new failure Build Source Stamp: [branch 10.1.x] 8044fc73b4e987d8e75a199dcdc907155dd0f6eb Steps: worker_preparation: 0 git: 0 shell: 0 shell_1: 0 shell_2: 0 shell_3: 0 shell_4: 0 shell_5: 0 compile: 1 shell_6: 0 shell_7: 0 shell_8: 2 -- ASF Buildbot - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.1.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.1.x by this push: new 8044fc73b4 Refactor to reduce pinning in HTTP/2 code when using virtual threads 8044fc73b4 is described below commit 8044fc73b4e987d8e75a199dcdc907155dd0f6eb Author: Mark Thomas AuthorDate: Wed Jul 26 10:34:38 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/StreamProcessor.java | 10 -- webapps/docs/changelog.xml| 4 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index e22afa030d..4b7990faea 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -22,6 +22,8 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import jakarta.servlet.ServletConnection; import jakarta.servlet.http.HttpServletResponse; @@ -55,6 +57,7 @@ class StreamProcessor extends AbstractProcessor { private static final Set H2_PSEUDO_HEADERS_REQUEST = new HashSet<>(); +private final Lock processLock = new ReentrantLock(); private final Http2UpgradeHandler handler; private final Stream stream; private SendfileData sendfileData = null; @@ -77,8 +80,9 @@ class StreamProcessor extends AbstractProcessor { final void process(SocketEvent event) { try { -// FIXME: the regular processor syncs on socketWrapper, but here this deadlocks -synchronized (this) { +// Note: The regular processor uses the socketWrapper lock, but using that here triggers a deadlock +processLock.lock(); +try { // HTTP/2 equivalent of AbstractConnectionHandler#process() without the // socket <-> processor mapping SocketState state = SocketState.CLOSED; @@ -134,6 +138,8 @@ class StreamProcessor extends AbstractProcessor { recycle(); } } +} finally { +processLock.unlock(); } } finally { handler.executeQueuedStream(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 460ea09733..246b17c9c3 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -122,6 +122,10 @@ certificateKeystoreFile attribute of an SSLHostConfigCertificate instance. (markt) + +Refactor HTTP/2 implementation to reduce pinning when using virtual +threads. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated (65ba2e1c7d -> 6090a5ed8a)
This is an automated email from the ASF dual-hosted git repository. markt pushed a change to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git from 65ba2e1c7d Update java.lang imports for Java 21 EA29 add 6090a5ed8a Refactor to reduce pinning in HTTP/2 code when using virtual threads No new revisions were added by this update. Summary of changes: java/org/apache/coyote/http2/StreamProcessor.java | 10 -- webapps/docs/changelog.xml| 4 2 files changed, 12 insertions(+), 2 deletions(-) - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
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 10443575cf Refactor to reduce pinning in HTTP/2 code when using virtual threads 10443575cf is described below commit 10443575cfa1740e72002ac28281d4ea3b3af24c Author: Mark Thomas AuthorDate: Wed Jul 26 10:34:38 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/StreamProcessor.java | 10 -- webapps/docs/changelog.xml| 4 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index 80c04ed5cc..6d4f4b90b4 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -21,6 +21,8 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpServletResponse; @@ -53,6 +55,7 @@ class StreamProcessor extends AbstractProcessor { private static final Set H2_PSEUDO_HEADERS_REQUEST = new HashSet<>(); +private final Lock processLock = new ReentrantLock(); private final Http2UpgradeHandler handler; private final Stream stream; @@ -74,8 +77,9 @@ class StreamProcessor extends AbstractProcessor { final void process(SocketEvent event) { try { -// FIXME: the regular processor syncs on socketWrapper, but here this deadlocks -synchronized (this) { +// Note: The regular processor uses the socketWrapper lock, but using that here triggers a deadlock +processLock.lock(); +try { // HTTP/2 equivalent of AbstractConnectionHandler#process() without the // socket <-> processor mapping SocketState state = SocketState.CLOSED; @@ -131,6 +135,8 @@ class StreamProcessor extends AbstractProcessor { recycle(); } } +} finally { +processLock.unlock(); } } finally { handler.executeQueuedStream(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 4f8ad42151..0d5be9f071 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -126,6 +126,10 @@ certificateKeystoreFile attribute of an SSLHostConfigCertificate instance. (markt) + +Refactor HTTP/2 implementation to reduce pinning when using virtual +threads. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Refactor to reduce pinning in HTTP/2 code when using virtual threads
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/9.0.x by this push: new 56ba62e2fc Refactor to reduce pinning in HTTP/2 code when using virtual threads 56ba62e2fc is described below commit 56ba62e2fc60c550a8b90a54452f78683a682ea0 Author: Mark Thomas AuthorDate: Wed Jul 26 10:34:38 2023 +0100 Refactor to reduce pinning in HTTP/2 code when using virtual threads --- java/org/apache/coyote/http2/StreamProcessor.java | 10 -- webapps/docs/changelog.xml| 4 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index 4b06ff9b71..8d8af36852 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -22,6 +22,8 @@ import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; import javax.servlet.http.HttpServletResponse; @@ -55,6 +57,7 @@ class StreamProcessor extends AbstractProcessor { private static final Set H2_PSEUDO_HEADERS_REQUEST = new HashSet<>(); +private final Lock processLock = new ReentrantLock(); private final Http2UpgradeHandler handler; private final Stream stream; private SendfileData sendfileData = null; @@ -77,8 +80,9 @@ class StreamProcessor extends AbstractProcessor { final void process(SocketEvent event) { try { -// FIXME: the regular processor syncs on socketWrapper, but here this deadlocks -synchronized (this) { +// Note: The regular processor uses the socketWrapper lock, but using that here triggers a deadlock +processLock.lock(); +try { // HTTP/2 equivalent of AbstractConnectionHandler#process() without the // socket <-> processor mapping SocketState state = SocketState.CLOSED; @@ -134,6 +138,8 @@ class StreamProcessor extends AbstractProcessor { recycle(); } } +} finally { +processLock.unlock(); } } finally { handler.executeQueuedStream(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 3d7f7256a8..f8b8f3f95e 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -143,6 +143,10 @@ certificateKeystoreFile attribute of an SSLHostConfigCertificate instance. (markt) + +Refactor HTTP/2 implementation to reduce pinning when using virtual +threads. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
Virtual threads, synchronized and pinning
Hi all, Following a report on the users list [1], I am currently looking at various refactoring to reduce pinning when using virtual threads. The process I am following is: - configure unit tests to run with virtual threads and pinning debug logging - run the Tomcat 11 test suite - use grep to find pinning reports in the test logs - fix the first instance I find - repeat I am doing this one issue at a time as some of the issues are quite complex as the objects are sync'd across multiple classes. Doing it all in one go would be a lot harder to review. Expect a series of commits addressing this over the next few days. Mark [1] https://lists.apache.org/thread/hw2mpbhf3436g694n06n3tgsm888kzwp - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org