Author: markt Date: Mon Nov 5 00:20:24 2012 New Revision: 1405681 URL: http://svn.apache.org/viewvc?rev=1405681&view=rev Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54086 Ensure only a single thread tries to close the selector. Prior to this change both the NioReceiverThread and the thread that stops it called closeSelector() I also reviewed all other accesses to this.selector and fixed a handful of other potential threading issues.
Modified: tomcat/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java tomcat/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java Modified: tomcat/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java?rev=1405681&r1=1405680&r2=1405681&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java (original) +++ tomcat/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java Mon Nov 5 00:20:24 2012 @@ -63,7 +63,7 @@ public abstract class ReceiverBase imple private int udpRxBufSize = 43800; private int udpTxBufSize = 25188; - private boolean listen = false; + private volatile boolean listen = false; private RxTaskPool pool; private boolean direct = true; private long tcpSelectorTimeout = 5000; Modified: tomcat/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java?rev=1405681&r1=1405680&r2=1405681&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java (original) +++ tomcat/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java Mon Nov 5 00:20:24 2012 @@ -30,6 +30,7 @@ import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.LinkedList; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; import org.apache.catalina.tribes.io.ObjectReader; import org.apache.catalina.tribes.transport.AbstractRxTask; @@ -54,7 +55,7 @@ public class NioReceiver extends Receive protected static final StringManager sm = StringManager.getManager(Constants.Package); - private Selector selector = null; + private AtomicReference<Selector> selector = new AtomicReference<>(); private ServerSocketChannel serverChannel = null; private DatagramChannel datagramChannel = null; @@ -118,7 +119,7 @@ public class NioReceiver extends Receive // Selector.open() isn't thread safe // http://bugs.sun.com/view_bug.do?bug_id=6427854 // Affects 1.6.0_29, fixed in 1.7.0_01 - selector = Selector.open(); + this.selector.set(Selector.open()); } // set the port the server channel will listen to //serverSocket.bind(new InetSocketAddress(getBind(), getTcpListenPort())); @@ -126,7 +127,7 @@ public class NioReceiver extends Receive // set non-blocking mode for the listening socket serverChannel.configureBlocking(false); // register the ServerSocketChannel with the Selector - serverChannel.register(selector, SelectionKey.OP_ACCEPT); + serverChannel.register(this.selector.get(), SelectionKey.OP_ACCEPT); //set up the datagram channel if (this.getUdpPort()>0) { @@ -147,12 +148,13 @@ public class NioReceiver extends Receive } public void addEvent(Runnable event) { + Selector selector = this.selector.get(); if ( selector != null ) { synchronized (events) { events.add(event); } if ( log.isTraceEnabled() ) log.trace("Adding event to selector:"+event); - if ( isListening() && selector!=null ) selector.wakeup(); + if ( isListening() ) selector.wakeup(); } } @@ -192,7 +194,7 @@ public class NioReceiver extends Receive long now = System.currentTimeMillis(); if ( (now-lastCheck) < getSelectorTimeout() ) return; //timeout - Selector tmpsel = selector; + Selector tmpsel = this.selector.get(); Set<SelectionKey> keys = (isListening()&&tmpsel!=null)?tmpsel.keys():null; if ( keys == null ) return; for (Iterator<SelectionKey> iter = keys.iterator(); iter.hasNext();) { @@ -250,7 +252,7 @@ public class NioReceiver extends Receive setListen(true); // Avoid NPEs if selector is set to null on stop. - Selector selector = this.selector; + Selector selector = this.selector.get(); if (selector!=null && datagramChannel!=null) { ObjectReader oreader = new ObjectReader(MAX_UDP_SIZE); //max size for a datagram packet @@ -346,6 +348,7 @@ public class NioReceiver extends Receive */ protected void stopListening() { setListen(false); + Selector selector = this.selector.get(); if (selector != null) { try { selector.wakeup(); @@ -353,14 +356,13 @@ public class NioReceiver extends Receive } catch (Exception x) { log.error(sm.getString("NioReceiver.stop.fail"), x); } finally { - selector = null; + this.selector.set(null); } } } private void closeSelector() throws IOException { - Selector selector = this.selector; - this.selector = null; + Selector selector = this.selector.getAndSet(null); if (selector==null) return; try { Iterator<SelectionKey> it = selector.keys().iterator(); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org