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]
