Author: markt Date: Sat Oct 5 22:21:40 2013 New Revision: 1529537 URL: http://svn.apache.org/r1529537 Log: Make access of dispatcher list on socket wrapper thread safe
Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java Modified: tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java?rev=1529537&r1=1529536&r2=1529537&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java (original) +++ tomcat/trunk/java/org/apache/coyote/AbstractProtocol.java Sat Oct 5 22:21:40 2013 @@ -18,6 +18,7 @@ package org.apache.coyote; import java.io.IOException; import java.net.InetAddress; +import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; @@ -616,14 +617,19 @@ public abstract class AbstractProtocol<S initSsl(wrapper, processor); SocketState state = SocketState.CLOSED; + Iterator<DispatchType> dispatches = null; do { - if (wrapper.hasNextDispatch()) { - // Associate with the processor with the connection as - // these calls may result in a nested call to process() - connections.put(socket, processor); - DispatchType nextDispatch = wrapper.getNextDispatch(); - state = processor.asyncDispatch( - nextDispatch.getSocketStatus()); + if (dispatches != null) { + if (dispatches.hasNext()) { + // Associate with the processor with the connection as + // these calls may result in a nested call to process() + connections.put(socket, processor); + DispatchType nextDispatch = dispatches.next(); + state = processor.asyncDispatch( + nextDispatch.getSocketStatus()); + } else { + dispatches = null; + } } else if (status == SocketStatus.DISCONNECT && !processor.isComet()) { // Do nothing here, just wait for it to get recycled @@ -670,9 +676,12 @@ public abstract class AbstractProtocol<S "], Status in: [" + status + "], State out: [" + state + "]"); } + if (dispatches == null || !dispatches.hasNext()) { + dispatches = wrapper.getIteratorAndClearDispatches(); + } } while (state == SocketState.ASYNC_END || state == SocketState.UPGRADING || - wrapper.hasNextDispatch() && state != SocketState.CLOSED); + dispatches.hasNext() && state != SocketState.CLOSED); if (state == SocketState.LONG) { // In the middle of processing a request/response. Keep the Modified: tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java?rev=1529537&r1=1529536&r2=1529537&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/AbstractEndpoint.java Sat Oct 5 22:21:40 2013 @@ -23,6 +23,7 @@ import java.net.InetSocketAddress; import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.HashMap; +import java.util.Iterator; import java.util.StringTokenizer; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; @@ -636,13 +637,11 @@ public abstract class AbstractEndpoint<S public void executeNonBlockingDispatches(SocketWrapper<S> socketWrapper) { - // Synchronise on the socket wrapper to ensure no other threads are - // working with the socket - synchronized (socketWrapper) { - while (socketWrapper.hasNextDispatch()) { - DispatchType dispatchType = socketWrapper.getNextDispatch(); - processSocket(socketWrapper, dispatchType.getSocketStatus(), false); - } + Iterator<DispatchType> dispatches = socketWrapper.getIteratorAndClearDispatches(); + + while (dispatches.hasNext()) { + DispatchType dispatchType = dispatches.next(); + processSocket(socketWrapper, dispatchType.getSocketStatus(), false); } } Modified: tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java?rev=1529537&r1=1529536&r2=1529537&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java (original) +++ tomcat/trunk/java/org/apache/tomcat/util/net/SocketWrapper.java Sat Oct 5 22:21:40 2013 @@ -17,8 +17,8 @@ package org.apache.tomcat.util.net; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; @@ -62,7 +62,7 @@ public class SocketWrapper<E> { */ private final Object writeThreadLock = new Object(); - private Set<DispatchType> dispatches = new LinkedHashSet<>(); + private Set<DispatchType> dispatches = new CopyOnWriteArraySet<>(); public SocketWrapper(E socket) { this.socket = socket; @@ -114,22 +114,22 @@ public class SocketWrapper<E> { } public Object getWriteThreadLock() { return writeThreadLock; } public void addDispatch(DispatchType dispatchType) { - dispatches.add(dispatchType); - } - public boolean hasNextDispatch() { - return dispatches.size() > 0; + synchronized (dispatches) { + dispatches.add(dispatchType); + } } - public DispatchType getNextDispatch() { - DispatchType result = null; - Iterator<DispatchType> iter = dispatches.iterator(); - if (iter.hasNext()) { - result = iter.next(); - iter.remove(); + public Iterator<DispatchType> getIteratorAndClearDispatches() { + Iterator<DispatchType> result; + synchronized (dispatches) { + result = dispatches.iterator(); + dispatches.clear(); } return result; } public void clearDispatches() { - dispatches.clear(); + synchronized (dispatches) { + dispatches.clear(); + } } public void reset(E socket, long timeout) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org