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 171a2cd Fix BZ 65448 for blocking IO 171a2cd is described below commit 171a2cdce037af67f67f474f48848ba19c9b8766 Author: Mark Thomas <ma...@apache.org> AuthorDate: Thu Jul 15 16:56:00 2021 +0100 Fix BZ 65448 for blocking IO If the write completes (from the application perspective) but the encrypted data is not fully written, the connection (from the client's perspective) will appear to hang until the client sends another request (pipelining) or the connection times out. --- java/org/apache/tomcat/util/net/NioEndpoint.java | 8 ++++++-- java/org/apache/tomcat/util/net/SecureNioChannel.java | 5 +++++ webapps/docs/changelog.xml | 6 ++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/java/org/apache/tomcat/util/net/NioEndpoint.java b/java/org/apache/tomcat/util/net/NioEndpoint.java index d4559bc..0f73308 100644 --- a/java/org/apache/tomcat/util/net/NioEndpoint.java +++ b/java/org/apache/tomcat/util/net/NioEndpoint.java @@ -1364,7 +1364,11 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> n = getSocket().write(buffer); if (n == -1) { throw new EOFException(); - } else if (n == 0) { + } else if (n == 0 && (buffer.hasRemaining() || getSocket().getOutboundRemaining() > 0)) { + // n == 0 could be an incomplete write but it could also + // indicate that a previous incomplete write of the + // outbound buffer (for TLS) has now completed. Only + // block if there is still data to write. writeBlocking = true; registerWriteInterest(); synchronized (writeLock) { @@ -1387,7 +1391,7 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> timeout = getWriteTimeout(); startNanos = 0; } - } while (buffer.hasRemaining()); + } while (buffer.hasRemaining() || getSocket().getOutboundRemaining() > 0); } else { do { n = getSocket().write(buffer); diff --git a/java/org/apache/tomcat/util/net/SecureNioChannel.java b/java/org/apache/tomcat/util/net/SecureNioChannel.java index 63af010..22e339f 100644 --- a/java/org/apache/tomcat/util/net/SecureNioChannel.java +++ b/java/org/apache/tomcat/util/net/SecureNioChannel.java @@ -801,6 +801,11 @@ public class SecureNioChannel extends NioChannel { return 0; } + if (!src.hasRemaining()) { + // Nothing left to write + return 0; + } + // The data buffer is empty, we can reuse the entire buffer. netOutBuffer.clear(); diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 8e28ef8..3a234be 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -140,6 +140,12 @@ connection that were trying to write when this happened would time out. (markt) </fix> + <fix> + <bug>65448</bug>: When using TLS with NIO, it was possible for a + blocking response write to hang just before the final TLS packet + associated with the response until the connection timed out at which + point the final packet would be sent and the connection closed. (markt) + </fix> </changelog> </subsection> <subsection name="Web applications"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org