You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/09/25 01:50:10 UTC

svn commit: r1526052 - /tomcat/trunk/java/org/apache/tomcat/util/net/AprEndpoint.java

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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org