Author: markt Date: Mon Nov 5 00:25:03 2012 New Revision: 1405682 URL: http://svn.apache.org/viewvc?rev=1405682&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/tc7.0.x/trunk/ (props changed) tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc7.0.x/trunk/ ------------------------------------------------------------------------------ Merged /tomcat/trunk:r1405681 Modified: tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java?rev=1405682&r1=1405681&r2=1405682&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/ReceiverBase.java Mon Nov 5 00:25:03 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/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java?rev=1405682&r1=1405681&r2=1405682&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java (original) +++ tomcat/tc7.0.x/trunk/java/org/apache/catalina/tribes/transport/nio/NioReceiver.java Mon Nov 5 00:25:03 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; @@ -58,7 +59,7 @@ public class NioReceiver extends Receive */ private static final String info = "NioReceiver/1.0"; - private Selector selector = null; + private AtomicReference<Selector> selector = new AtomicReference<Selector>(); private ServerSocketChannel serverChannel = null; private DatagramChannel datagramChannel = null; @@ -136,7 +137,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())); @@ -144,7 +145,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) { @@ -165,12 +166,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(); } } @@ -210,7 +212,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();) { @@ -263,7 +265,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 @@ -359,6 +361,7 @@ public class NioReceiver extends Receive */ protected void stopListening() { setListen(false); + Selector selector = this.selector.get(); if (selector != null) { try { selector.wakeup(); @@ -366,14 +369,13 @@ public class NioReceiver extends Receive } catch (Exception x) { log.error("Unable to close cluster receiver selector.", 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(); Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1405682&r1=1405681&r2=1405682&view=diff ============================================================================== --- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Mon Nov 5 00:25:03 2012 @@ -171,6 +171,10 @@ Add getSessionIdsFull operation to mbeans-descriptor. listSessionIdsFull no longer exist. (kfujino) </fix> + <fix> + <bug>54086</bug>: Fix threading issue when stopping an + <code>NioReceiver</code>. (markt) + </fix> </changelog> </subsection> <subsection name="Tribes"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org