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

Reply via email to