Author: markt Date: Tue Sep 24 23:50:09 2013 New Revision: 1526052 URL: http://svn.apache.org/r1526052 Log: Removal of a socket from the poller needs to happen on the poller thread as removal, like addition, is not thread safe. Removal of a socket from the poller needs to remove the socket from the addListif it is present otherwise the closed socket could end up in the poller.
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=1526052&r1=1526051&r2=1526052&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java Tue Sep 24 23:50:09 2013 @@ -907,7 +907,7 @@ public class AprEndpoint extends Abstrac // countDownConnection() in that case Poller poller = this.poller; if (poller != null) { - poller.removeFromPoller(socket); + poller.remove(socket); } connections.remove(Long.valueOf(socket)); destroySocket(socket, running); @@ -1220,6 +1220,19 @@ public class AprEndpoint extends Abstrac } } + public boolean remove(long socket) { + for (int i = 0; i < size; i++) { + if (sockets[i] == socket) { + sockets[i] = sockets[size - 1]; + timeouts[i] = timeouts[size - 1]; + flags[size] = flags[size -1]; + size--; + return true; + } + } + return false; + } + public void duplicate(SocketList copy) { copy.size = size; copy.pos = pos; @@ -1276,6 +1289,12 @@ public class AprEndpoint extends Abstrac /** + * List of sockets to be removed from the poller. + */ + private SocketList removeList = null; + + + /** * Structure used for storing timeouts. */ private SocketTimeouts timeouts = null; @@ -1349,6 +1368,7 @@ public class AprEndpoint extends Abstrac desc = new long[actualPollerSize * 2]; connectionCount = 0; addList = new SocketList(defaultPollerSize); + removeList = new SocketList(defaultPollerSize); } @@ -1464,8 +1484,10 @@ public class AprEndpoint extends Abstrac } } + /** - * Add specified socket to one of the pollers. + * Add specified socket to one of the pollers. Must only be called from + * {@link Poller#run()}. */ private boolean addToPoller(long socket, int events) { int rv = -1; @@ -1482,10 +1504,19 @@ public class AprEndpoint extends Abstrac return false; } + + protected void remove(long socket) { + synchronized (this) { + removeList.add(socket, 0, 0); + } + } + + /** - * Remove specified socket from the pollers. + * Remove specified socket from the pollers. Must only be called from + * {@link Poller#run()}. */ - protected boolean removeFromPoller(long socket) { + private boolean removeFromPoller(long socket) { int rv = -1; for (int i = 0; i < pollers.length; i++) { if (pollerSpace[i] < actualPollerSize) { @@ -1560,7 +1591,7 @@ public class AprEndpoint extends Abstrac int maintain = 0; SocketList localAddList = new SocketList(getMaxConnections()); - + SocketList localRemoveList = new SocketList(getMaxConnections()); // Loop until we receive a shutdown command while (pollerRunning) { @@ -1598,7 +1629,18 @@ public class AprEndpoint extends Abstrac } try { - // Add sockets which are waiting to the poller + // Duplicate the add and remove lists so that the syncs are + // minimised + if (removeList.size() > 0) { + synchronized (this) { + // Duplicate to another list, so that the syncing is + // minimal + removeList.duplicate(localRemoveList); + removeList.clear(); + } + } else { + localAddList.clear(); + } if (addList.size() > 0) { synchronized (this) { // Duplicate to another list, so that the syncing is @@ -1606,6 +1648,22 @@ public class AprEndpoint extends Abstrac addList.duplicate(localAddList); addList.clear(); } + } else { + localAddList.clear(); + } + + // Remove sockets + if (localRemoveList.size() > 0) { + SocketInfo info = localRemoveList.get(); + while (info != null) { + localAddList.remove(info.socket); + removeFromPoller(info.socket); + info = localRemoveList.get(); + } + } + + // Add sockets which are waiting to the poller + if (localAddList.size() > 0) { SocketInfo info = localAddList.get(); while (info != null) { if (log.isDebugEnabled()) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org