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 4025253bf4d29782fb8a5a39dd487ad9ebc23798 Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri Feb 18 14:41:21 2022 +0000 s --- java/org/apache/tomcat/util/compat/JreCompat.java | 9 ++- java/org/apache/tomcat/util/net/NioChannel.java | 9 +-- java/org/apache/tomcat/util/net/NioEndpoint.java | 80 ++++++++++++++--------- 3 files changed, 60 insertions(+), 38 deletions(-) diff --git a/java/org/apache/tomcat/util/compat/JreCompat.java b/java/org/apache/tomcat/util/compat/JreCompat.java index 3850ef7..162eccc 100644 --- a/java/org/apache/tomcat/util/compat/JreCompat.java +++ b/java/org/apache/tomcat/util/compat/JreCompat.java @@ -43,6 +43,7 @@ public class JreCompat { private static final JreCompat instance; private static StringManager sm = StringManager.getManager(JreCompat.class.getPackage().getName()); + private static final boolean jre11Available; private static final boolean jre9Available; private static final boolean jre8Available; @@ -62,9 +63,10 @@ public class JreCompat { jre8Available = true; } else { instance = new JreCompat(); - jre9Available = false; jre8Available = false; + jre9Available = false; } + jre11Available = instance.jarFileRuntimeMajorVersion() >= 11; } @@ -80,6 +82,11 @@ public class JreCompat { } + public static boolean isJre11Available() { + return jre11Available; + } + + @SuppressWarnings("unused") public void setUseServerCipherSuitesOrder(SSLParameters engine, boolean useCipherSuitesOrder) { throw new UnsupportedOperationException(sm.getString("jreCompat.noServerCipherSuiteOrder")); diff --git a/java/org/apache/tomcat/util/net/NioChannel.java b/java/org/apache/tomcat/util/net/NioChannel.java index 4874d36..b718e39 100644 --- a/java/org/apache/tomcat/util/net/NioChannel.java +++ b/java/org/apache/tomcat/util/net/NioChannel.java @@ -270,11 +270,7 @@ public class NioChannel implements ByteChannel, ScatteringByteChannel, Gathering return appReadBufHandler; } - static final NioChannel CLOSED_NIO_CHANNEL = new ClosedNioChannel(); - public static class ClosedNioChannel extends NioChannel { - public ClosedNioChannel() { - super(SocketBufferHandler.EMPTY); - } + static final NioChannel CLOSED_NIO_CHANNEL = new NioChannel(SocketBufferHandler.EMPTY) { @Override public void close() throws IOException { } @@ -314,5 +310,6 @@ public class NioChannel implements ByteChannel, ScatteringByteChannel, Gathering public String toString() { return "Closed NioChannel"; } - } + }; + } diff --git a/java/org/apache/tomcat/util/net/NioEndpoint.java b/java/org/apache/tomcat/util/net/NioEndpoint.java index 579ed4b..3e929d2 100644 --- a/java/org/apache/tomcat/util/net/NioEndpoint.java +++ b/java/org/apache/tomcat/util/net/NioEndpoint.java @@ -52,9 +52,9 @@ import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.IntrospectionUtils; import org.apache.tomcat.util.collections.SynchronizedQueue; import org.apache.tomcat.util.collections.SynchronizedStack; +import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.compat.JrePlatform; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; -import org.apache.tomcat.util.net.NioChannel.ClosedNioChannel; import org.apache.tomcat.util.net.jsse.JSSESupport; /** @@ -1335,7 +1335,7 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> private int fillReadBuffer(boolean block, ByteBuffer to) throws IOException { int nRead; NioChannel socket = getSocket(); - if (socket instanceof ClosedNioChannel) { + if (socket == NioChannel.CLOSED_NIO_CHANNEL) { throw new ClosedChannelException(); } if (block) { @@ -1665,8 +1665,14 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> @Override protected void doRun() { - NioChannel socket = socketWrapper.getSocket(); - SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); + /* + * Do not cache and re-use the value of socketWrapper.getSocket() in + * this method. If the socket closes the value will be updated to + * CLOSED_NIO_CHANNEL and the previous value potentially re-used for + * a new connection. That can result in a stale cached value which + * in turn can result in unintentionally closing currently active + * connections. + */ Poller poller = NioEndpoint.this.poller; if (poller == null) { socketWrapper.close(); @@ -1676,27 +1682,25 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> try { int handshake = -1; try { - if (key != null) { - if (socket.isHandshakeComplete()) { - // No TLS handshaking required. Let the handler - // process this socket / event combination. - handshake = 0; - } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT || - event == SocketEvent.ERROR) { - // Unable to complete the TLS handshake. Treat it as - // if the handshake failed. - handshake = -1; - } else { - handshake = socket.handshake(key.isReadable(), key.isWritable()); - // The handshake process reads/writes from/to the - // socket. status may therefore be OPEN_WRITE once - // the handshake completes. However, the handshake - // happens when the socket is opened so the status - // must always be OPEN_READ after it completes. It - // is OK to always set this as it is only used if - // the handshake completes. - event = SocketEvent.OPEN_READ; - } + if (socketWrapper.getSocket().isHandshakeComplete()) { + // No TLS handshaking required. Let the handler + // process this socket / event combination. + handshake = 0; + } else if (event == SocketEvent.STOP || event == SocketEvent.DISCONNECT || + event == SocketEvent.ERROR) { + // Unable to complete the TLS handshake. Treat it as + // if the handshake failed. + handshake = -1; + } else { + handshake = socketWrapper.getSocket().handshake(event == SocketEvent.OPEN_READ, event == SocketEvent.OPEN_WRITE); + // The handshake process reads/writes from/to the + // socket. status may therefore be OPEN_WRITE once + // the handshake completes. However, the handshake + // happens when the socket is opened so the status + // must always be OPEN_READ after it completes. It + // is OK to always set this as it is only used if + // the handshake completes. + event = SocketEvent.OPEN_READ; } } catch (IOException x) { handshake = -1; @@ -1715,23 +1719,23 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> state = getHandler().process(socketWrapper, event); } if (state == SocketState.CLOSED) { - poller.cancelledKey(key, socketWrapper); + poller.cancelledKey(getSelectionKey(), socketWrapper); } } else if (handshake == -1 ) { getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL); - poller.cancelledKey(key, socketWrapper); - } else if (handshake == SelectionKey.OP_READ) { + poller.cancelledKey(getSelectionKey(), socketWrapper); + } else if (handshake == SelectionKey.OP_READ){ socketWrapper.registerReadInterest(); } else if (handshake == SelectionKey.OP_WRITE){ socketWrapper.registerWriteInterest(); } } catch (CancelledKeyException cx) { - socket.getPoller().cancelledKey(key, socketWrapper); + poller.cancelledKey(getSelectionKey(), socketWrapper); } catch (VirtualMachineError vme) { ExceptionUtils.handleThrowable(vme); } catch (Throwable t) { - log.error("", t); - socket.getPoller().cancelledKey(key, socketWrapper); + log.error(sm.getString("endpoint.processing.fail"), t); + poller.cancelledKey(getSelectionKey(), socketWrapper); } finally { socketWrapper = null; event = null; @@ -1741,6 +1745,20 @@ public class NioEndpoint extends AbstractJsseEndpoint<NioChannel,SocketChannel> } } } + + private SelectionKey getSelectionKey() { + // Shortcut for Java 11 onwards + if (JreCompat.isJre11Available()) { + return null; + } + + SocketChannel socketChannel = socketWrapper.getSocket().getIOChannel(); + if (socketChannel == null) { + return null; + } + + return socketChannel.keyFor(NioEndpoint.this.poller.getSelector()); + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org