Author: markt Date: Thu Dec 18 14:14:50 2014 New Revision: 1646461 URL: http://svn.apache.org/r1646461 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=57340 Ensure that Socket and SocketWrapper are only returned to the cache once on socket close (it is possible for multiple threads to call close concurrently).
Modified: tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Modified: tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java?rev=1646461&r1=1646460&r2=1646461&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/net/NioEndpoint.java Thu Dec 18 14:14:50 2014 @@ -950,15 +950,16 @@ public class NioEndpoint extends Abstrac addEvent(r); } - public void cancelledKey(SelectionKey key, SocketStatus status) { + public KeyAttachment cancelledKey(SelectionKey key, SocketStatus status) { + KeyAttachment ka = null; try { - if ( key == null ) return;//nothing to do - KeyAttachment ka = (KeyAttachment) key.attachment(); + if ( key == null ) return null;//nothing to do + ka = (KeyAttachment) key.attachment(); if (ka != null && ka.isComet() && status != null) { ka.setComet(false);//to avoid a loop if (status == SocketStatus.TIMEOUT ) { if (processSocket(ka, status, true)) { - return; // don't close on comet timeout + return null; // don't close on comet timeout } } else { // Don't dispatch if the lines below are cancelling the key @@ -1005,6 +1006,7 @@ public class NioEndpoint extends Abstrac ExceptionUtils.handleThrowable(e); if (log.isDebugEnabled()) log.error("",e); } + return ka; } /** * The background thread that listens for incoming TCP/IP connections and @@ -1559,13 +1561,20 @@ public class NioEndpoint extends Abstrac // Close socket and pool try { ka.setComet(false); - socket.getPoller().cancelledKey(key, SocketStatus.ERROR); - if (running && !paused) { - nioChannels.push(socket); - } - socket = null; - if (running && !paused) { - keyCache.push(ka); + if (socket.getPoller().cancelledKey(key, SocketStatus.ERROR) != null) { + // SocketWrapper (attachment) was removed from the + // key - recycle both. This can only happen once + // per attempted closure so it is used to determine + // whether or not to return socket and ka to + // their respective caches. We do NOT want to do + // this more than once - see BZ 57340. + if (running && !paused) { + nioChannels.push(socket); + } + socket = null; + if (running && !paused) { + keyCache.push(ka); + } } ka = null; } catch (Exception x) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org