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

Reply via email to