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 8a83c3c42d Improve stability of APR/native connector.
8a83c3c42d is described below

commit 8a83c3c42d20762782678932c14005cd3397a018
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jun 26 10:05:59 2025 +0100

    Improve stability of APR/native connector.
    
    This addresses at least some of the intermittent issues observed with
    the APR unit tests.
---
 java/org/apache/tomcat/util/net/AprEndpoint.java | 82 ++++++++++++++++--------
 webapps/docs/changelog.xml                       |  3 +
 2 files changed, 57 insertions(+), 28 deletions(-)

diff --git a/java/org/apache/tomcat/util/net/AprEndpoint.java 
b/java/org/apache/tomcat/util/net/AprEndpoint.java
index 83217cd31b..cc8b5d1c8c 100644
--- a/java/org/apache/tomcat/util/net/AprEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AprEndpoint.java
@@ -651,17 +651,8 @@ public class AprEndpoint extends 
AbstractEndpoint<Long,Long> implements SNICallB
 
             // Close the SocketWrapper for each open connection - this should
             // trigger a IOException when the app (or container) tries to 
write.
-            // Use the blocking status write lock as a proxy for a lock on
-            // writing to the socket. Don't want to close it while another
-            // thread is writing as that could trigger a JVM crash.
             for (SocketWrapperBase<Long> socketWrapper : connections.values()) 
{
-                WriteLock wl = ((AprSocketWrapper) 
socketWrapper).getBlockingStatusWriteLock();
-                wl.lock();
-                try {
-                    socketWrapper.close();
-                } finally {
-                    wl.unlock();
-                }
+                socketWrapper.close();
             }
 
             for (Long socket : connections.keySet()) {
@@ -2382,6 +2373,17 @@ public class AprEndpoint extends 
AbstractEndpoint<Long,Long> implements SNICallB
         }
 
 
+        @Override
+        public void close() {
+            Lock lock = getLock();
+            lock.lock();
+            try {
+                super.close();
+            } finally {
+                lock.unlock();
+            }
+        }
+
         @Override
         protected void doClose() {
             if (log.isDebugEnabled()) {
@@ -2585,25 +2587,31 @@ public class AprEndpoint extends 
AbstractEndpoint<Long,Long> implements SNICallB
 
         @Override
         protected void populateRemoteAddr() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_REMOTE, socket);
                 remoteAddr = Address.getip(sa);
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noRemoteAddr", 
getSocket()), e);
+            } finally {
+                lock.unlock();
             }
         }
 
 
         @Override
         protected void populateRemoteHost() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_REMOTE, socket);
                 remoteHost = Address.getnameinfo(sa, 0);
@@ -2612,68 +2620,86 @@ public class AprEndpoint extends 
AbstractEndpoint<Long,Long> implements SNICallB
                 }
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noRemoteHost", 
getSocket()), e);
+            } finally {
+                lock.unlock();
             }
         }
 
 
         @Override
         protected void populateRemotePort() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_REMOTE, socket);
                 Sockaddr addr = Address.getInfo(sa);
                 remotePort = addr.port;
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noRemotePort", 
getSocket()), e);
+            } finally {
+                lock.unlock();
             }
         }
 
 
         @Override
         protected void populateLocalName() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_LOCAL, socket);
                 localName = Address.getnameinfo(sa, 0);
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noLocalName"), e);
+            } finally {
+                lock.unlock();
             }
         }
 
 
         @Override
         protected void populateLocalAddr() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_LOCAL, socket);
                 localAddr = Address.getip(sa);
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noLocalAddr"), e);
+            } finally {
+                lock.unlock();
             }
         }
 
 
         @Override
         protected void populateLocalPort() {
-            if (isClosed()) {
-                return;
-            }
+            Lock lock = getLock();
+            lock.lock();
             try {
+                if (isClosed()) {
+                    return;
+                }
                 long socket = getSocket().longValue();
                 long sa = Address.get(Socket.APR_LOCAL, socket);
                 Sockaddr addr = Address.getInfo(sa);
                 localPort = addr.port;
             } catch (Exception e) {
                 log.warn(sm.getString("endpoint.warn.noLocalPort"), e);
+            } finally {
+                lock.unlock();
             }
         }
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 3d466f5684..04336f0129 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -145,6 +145,9 @@
         Fix JMX value for <code>keepAliveCount</code> on the endpoint. Also add
         the value of <code>useVirtualThreads</code> in JMX. (remm)
       </fix>
+      <fix>
+        Improve stability of APR/native connector. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Jasper">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to