Author: markt Date: Wed Oct 9 13:37:05 2013 New Revision: 1530601 URL: http://svn.apache.org/r1530601 Log: Fix issue observed with APR, WebSocket and blocking messages. If one client freezes the system freezes once the network buffers are full. When the client unfroze, the backlog of traffic was cleared and then one or more connections were closed unexpectedly. This was caused by incorrectly setting a very short timeout when readding the socket to the Poller after only a subset of the registered events triggered.
Modified: tomcat/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1530599 Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java?rev=1530601&r1=1530600&r2=1530601&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Oct 9 13:37:05 2013 @@ -1132,16 +1132,24 @@ public class AprEndpoint extends Abstrac size++; } - public boolean remove(long socket) { + /** + * Removes the specified socket from the poller. + * + * @returns The configured timeout for the socket or zero if the socket + * was not in the list of socket timeouts + */ + public long remove(long socket) { + long result = 0; for (int i = 0; i < size; i++) { if (sockets[i] == socket) { + result = timeouts[i]; sockets[i] = sockets[size - 1]; timeouts[i] = timeouts[size - 1]; size--; - return true; + break; } } - return false; + return result; } public long check(long date) { @@ -1769,7 +1777,7 @@ public class AprEndpoint extends Abstrac pollerSpace[i] += rv; connectionCount.addAndGet(-rv); for (int n = 0; n < rv; n++) { - timeouts.remove(desc[n*2+1]); + long timeout = timeouts.remove(desc[n*2+1]); AprSocketWrapper wrapper = connections.get( Long.valueOf(desc[n*2+1])); if (getLog().isDebugEnabled()) { @@ -1877,13 +1885,29 @@ public class AprEndpoint extends Abstrac error = true; closeSocket(desc[n*2+1]); } - if (!error) { + if (!error && wrapper.pollerFlags != 0) { // If socket was registered for multiple events but // only some of the occurred, re-register for the // remaining events. - if (wrapper.pollerFlags != 0) { - add(desc[n*2+1], 1, wrapper.pollerFlags); + // timeout is the value of System.currentTimeMillis() that + // was set as the point that the socket will timeout. When + // adding to the poller, the timeout from now in + // milliseconds is required. + // So first, subtract the current timestamp + if (timeout > 0) { + timeout = timeout - System.currentTimeMillis(); + } + // If the socket should have already expired by now, + // re-add it with a very short timeout + if (timeout <= 0) { + timeout = 1; + } + // Should be impossible but just in case since timeout will + // be cast to an int. + if (timeout > Integer.MAX_VALUE) { + timeout = Integer.MAX_VALUE; } + add(desc[n*2+1], (int) timeout, wrapper.pollerFlags); } } else { // Unknown event --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org