Author: markt
Date: Wed Oct 9 13:31:03 2013
New Revision: 1530599
URL: http://svn.apache.org/r1530599
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/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java
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=1530599&r1=1530598&r2=1530599&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Wed Oct 9
13:31:03 2013
@@ -1155,16 +1155,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) {
@@ -1792,7 +1800,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()) {
@@ -1903,13 +1911,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: [email protected]
For additional commands, e-mail: [email protected]