This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit 6062ded9a0da5141c8a47bd6febf8d496eaa1fd3
Author: opencode <[email protected]>
AuthorDate: Wed Sep 30 22:38:26 2026 +0200

    Bound connect and read operations in TcpSender with timeouts since the 
heartbeat runs on the shared server utility executor, and close connections on 
read failure
---
 java/org/apache/catalina/ha/backend/TcpSender.java | 39 ++++++++++++++++------
 1 file changed, 29 insertions(+), 10 deletions(-)

diff --git a/java/org/apache/catalina/ha/backend/TcpSender.java 
b/java/org/apache/catalina/ha/backend/TcpSender.java
index 8b13950894..203541e7ed 100644
--- a/java/org/apache/catalina/ha/backend/TcpSender.java
+++ b/java/org/apache/catalina/ha/backend/TcpSender.java
@@ -44,6 +44,16 @@ public class TcpSender implements Sender {
     private static final Log log = LogFactory.getLog(TcpSender.class);
     private static final StringManager sm = 
StringManager.getManager(TcpSender.class);
 
+    /**
+     * Timeout, in milliseconds, when connecting to a proxy.
+     */
+    private static final int CONNECT_TIMEOUT = 5000;
+
+    /**
+     * Timeout, in milliseconds, when reading a response from a proxy.
+     */
+    private static final int READ_TIMEOUT = 5000;
+
     /**
      * The heartbeat listener configuration.
      */
@@ -115,16 +125,19 @@ public class TcpSender implements Sender {
         for (int i = 0; i < connections.length; i++) {
             if (connections[i] == null) {
                 try {
+                    connections[i] = new Socket();
+                    // Never block the periodic event thread indefinitely
+                    connections[i].setSoTimeout(READ_TIMEOUT);
                     if (config.getHost() != null) {
-                        connections[i] = new Socket();
                         InetAddress addr = 
InetAddress.getByName(config.getHost());
                         InetSocketAddress addrs = new InetSocketAddress(addr, 
0);
                         connections[i].setReuseAddress(true);
                         connections[i].bind(addrs);
                         addrs = new InetSocketAddress(proxies[i].address, 
proxies[i].port);
-                        connections[i].connect(addrs);
+                        connections[i].connect(addrs, CONNECT_TIMEOUT);
                     } else {
-                        connections[i] = new Socket(proxies[i].address, 
proxies[i].port);
+                        connections[i].connect(new 
InetSocketAddress(proxies[i].address, proxies[i].port),
+                                CONNECT_TIMEOUT);
                     }
                     connectionReaders[i] = new BufferedReader(new 
InputStreamReader(connections[i].getInputStream()));
                     connectionWriters[i] = new BufferedWriter(new 
OutputStreamWriter(connections[i].getOutputStream()));
@@ -156,12 +169,14 @@ public class TcpSender implements Sender {
             }
 
             /* Read httpd answer */
-            String responseStatus = connectionReaders[i].readLine();
-            if (responseStatus == null) {
-                log.error(sm.getString("tcpSender.responseError"));
-                close(i);
-                continue;
-            } else {
+            try {
+                String responseStatus = connectionReaders[i].readLine();
+                if (responseStatus == null) {
+                    log.error(sm.getString("tcpSender.responseError"));
+                    close(i);
+                    continue;
+                }
+
                 int firstSpace = responseStatus.indexOf(' ');
                 int secondSpace = responseStatus.indexOf(' ', firstSpace + 1);
                 if (firstSpace < 0 || secondSpace < 0 || secondSpace <= 
firstSpace + 1) {
@@ -234,8 +249,12 @@ public class TcpSender implements Sender {
                         }
                     }
                 }
+            } catch (IOException e) {
+                // Includes read timeouts. Close the connection so it is not
+                // reused in a desynchronised state
+                log.error(sm.getString("tcpSender.responseError"), e);
+                close(i);
             }
-
         }
 
         return 0;


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to