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: [email protected]
For additional commands, e-mail: [email protected]