Author: markt Date: Wed Feb 23 11:58:47 2011 New Revision: 1073711 URL: http://svn.apache.org/viewvc?rev=1073711&view=rev Log: Better handling in acceptor threads if server hits ulimit for open files
Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1073711&r1=1073710&r2=1073711&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Wed Feb 23 11:58:47 2011 @@ -104,6 +104,9 @@ public abstract class AbstractEndpoint { public static final String SSL_ATTR_ALLOW_UNSAFE_RENEG = "allowUnsafeLegacyRenegotiation"; + private static final int INITIAL_ERROR_DELAY = 50; + private static final int MAX_ERROR_DELAY = 1600; + // ----------------------------------------------------------------- Fields @@ -614,7 +617,37 @@ public abstract class AbstractEndpoint { } else return -1; } - + /** + * Provides a common approach for sub-classes to handle exceptions where a + * delay is required to prevent a Thread from entering a tight loop which + * will consume CPU and may also trigger large amounts of logging. For + * example, this can happen with the Acceptor thread if the ulimit for open + * files is reached. + * + * @param currentErrorDelay The current delay beign applied on failure + * @return The delay to apply on the next failure + */ + protected int handleExceptionWithDelay(int currentErrorDelay) { + // Don't delay on first exception + if (currentErrorDelay > 0) { + try { + Thread.sleep(currentErrorDelay); + } catch (InterruptedException e) { + // Ignore + } + } + + // On subsequent exceptions, start the delay at 50ms, doubling the delay + // on every subsequent exception until the delay reaches 1.6 seconds. + if (currentErrorDelay == 0) { + return INITIAL_ERROR_DELAY; + } else if (currentErrorDelay < MAX_ERROR_DELAY) { + return currentErrorDelay * 2; + } else { + return MAX_ERROR_DELAY; + } + + } // -------------------- SSL related properties -------------------- Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1073711&r1=1073710&r2=1073711&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Feb 23 11:58:47 2011 @@ -914,6 +914,8 @@ public class AprEndpoint extends Abstrac @Override public void run() { + int errorDelay = 0; + // Loop until we receive a shutdown command while (running) { @@ -932,8 +934,21 @@ public class AprEndpoint extends Abstrac try { //if we have reached max connections, wait awaitConnection(); - // Accept the next incoming connection from the server socket - long socket = Socket.accept(serverSock); + + long socket = 0; + try { + // Accept the next incoming connection from the server + // socket + socket = Socket.accept(serverSock); + } catch (Exception e) { + // Introduce delay if necessary + errorDelay = handleExceptionWithDelay(errorDelay); + // re-throw + throw e; + } + // Successful accept, reset the error delay + errorDelay = 0; + //increment socket count countUpConnection(); /* Modified: tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1073711&r1=1073710&r2=1073711&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Wed Feb 23 11:58:47 2011 @@ -183,6 +183,8 @@ public class JIoEndpoint extends Abstrac @Override public void run() { + int errorDelay = 0; + // Loop until we receive a shutdown command while (running) { @@ -200,10 +202,22 @@ public class JIoEndpoint extends Abstrac } try { //if we have reached max connections, wait - awaitConnection(); - // Accept the next incoming connection from the server socket - Socket socket = serverSocketFactory.acceptSocket(serverSocket); - + awaitConnection(); + + Socket socket = null; + try { + // Accept the next incoming connection from the server + // socket + socket = serverSocketFactory.acceptSocket(serverSocket); + } catch (IOException ioe) { + // Introduce delay if necessary + errorDelay = handleExceptionWithDelay(errorDelay); + // re-throw + throw ioe; + } + // Successful accept, reset the error delay + errorDelay = 0; + // Configure the socket if (setSocketOptions(socket)) { // Hand this socket off to an appropriate processor Modified: tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1073711&r1=1073710&r2=1073711&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Wed Feb 23 11:58:47 2011 @@ -794,7 +794,9 @@ public class NioEndpoint extends Abstrac */ @Override public void run() { - + + int errorDelay = 0; + // Loop until we receive a shutdown command while (running) { @@ -813,8 +815,21 @@ public class NioEndpoint extends Abstrac try { //if we have reached max connections, wait awaitConnection(); - // Accept the next incoming connection from the server socket - SocketChannel socket = serverSock.accept(); + + SocketChannel socket = null; + try { + // Accept the next incoming connection from the server + // socket + socket = serverSock.accept(); + } catch (IOException ioe) { + // Introduce delay if necessary + errorDelay = handleExceptionWithDelay(errorDelay); + // re-throw + throw ioe; + } + // Successful accept, reset the error delay + errorDelay = 0; + // Hand this socket off to an appropriate processor //TODO FIXME - this is currently a blocking call, meaning we will be blocking //further accepts until there is a thread available. Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1073711&r1=1073710&r2=1073711&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Wed Feb 23 11:58:47 2011 @@ -130,6 +130,14 @@ <bug>50780</bug>: Fix memory leak in APR implementation of AJP connector introduced by the refactoring for <bug>49884</bug>. (markt) </fix> + <fix> + If server configuration errors and/or faulty applications caused the + ulimit for open files to be reached, the acceptor threads for all + connectors could enter a tight loop. This loop consumed CPU and also + logged an error message for every iteration of the loop which lead to + large log files being generated. The acceptors have been enhanced to + better handle this situation. (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