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

Reply via email to