summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2013-07-09 23:39:23 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-07-09 23:39:23 +0000
commit131dcd13038e931d75cd3a63d14df0527670f7f3 (patch)
tree229204c89a42c3d608daa216de6f7a60ceb05367
parentec618403efee992f232f017fbff1afff6cfa0de3 (diff)
parent57656d21f772aacbe0d05e54b1274f4c58993a52 (diff)
downloadlibcore-131dcd13038e931d75cd3a63d14df0527670f7f3.zip
libcore-131dcd13038e931d75cd3a63d14df0527670f7f3.tar.gz
libcore-131dcd13038e931d75cd3a63d14df0527670f7f3.tar.bz2
Merge "Fix Selector to allow read and write at the same time."
-rw-r--r--luni/src/main/java/java/nio/SelectorImpl.java19
-rw-r--r--luni/src/test/java/libcore/java/nio/channels/SelectorTest.java41
2 files changed, 45 insertions, 15 deletions
diff --git a/luni/src/main/java/java/nio/SelectorImpl.java b/luni/src/main/java/java/nio/SelectorImpl.java
index 02fdf54..447157b 100644
--- a/luni/src/main/java/java/nio/SelectorImpl.java
+++ b/luni/src/main/java/java/nio/SelectorImpl.java
@@ -254,24 +254,25 @@ final class SelectorImpl extends AbstractSelector {
pollFd.userData = null;
int ops = key.interestOpsNoCheck();
- int selectedOp = 0;
+ int selectedOps = 0;
if ((pollFd.revents & POLLIN) != 0) {
- selectedOp = ops & (OP_ACCEPT | OP_READ);
- } else if ((pollFd.revents & POLLOUT) != 0) {
+ selectedOps |= ops & (OP_ACCEPT | OP_READ);
+ }
+ if ((pollFd.revents & POLLOUT) != 0) {
if (key.isConnected()) {
- selectedOp = ops & OP_WRITE;
+ selectedOps |= ops & OP_WRITE;
} else {
- selectedOp = ops & OP_CONNECT;
+ selectedOps |= ops & OP_CONNECT;
}
}
- if (selectedOp != 0) {
+ if (selectedOps != 0) {
boolean wasSelected = mutableSelectedKeys.contains(key);
- if (wasSelected && key.readyOps() != selectedOp) {
- key.setReadyOps(key.readyOps() | selectedOp);
+ if (wasSelected && key.readyOps() != selectedOps) {
+ key.setReadyOps(key.readyOps() | selectedOps);
++readyKeyCount;
} else if (!wasSelected) {
- key.setReadyOps(selectedOp);
+ key.setReadyOps(selectedOps);
mutableSelectedKeys.add(key);
++readyKeyCount;
}
diff --git a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
index 4fc70c4..ec20c2a 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SelectorTest.java
@@ -18,6 +18,7 @@ package libcore.java.nio.channels;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
+import java.nio.ByteBuffer;
import java.nio.channels.NoConnectionPendingException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
@@ -129,16 +130,44 @@ public class SelectorTest extends TestCase {
}
}
- /**
- * We previously leaked a file descriptor for each selector instance created.
- *
- * http://code.google.com/p/android/issues/detail?id=5993
- * http://code.google.com/p/android/issues/detail?id=4825
- */
+ // We previously leaked a file descriptor for each selector instance created.
+ //
+ // http://code.google.com/p/android/issues/detail?id=5993
+ // http://code.google.com/p/android/issues/detail?id=4825
public void testLeakingPipes() throws IOException {
for (int i = 0; i < 2000; i++) {
Selector selector = Selector.open();
selector.close();
}
}
+
+ public void test_57456() throws Exception {
+ Selector selector = Selector.open();
+ ServerSocketChannel ssc = ServerSocketChannel.open();
+
+ try {
+ // Connect.
+ ssc.configureBlocking(false);
+ ssc.socket().bind(null);
+ SocketChannel sc = SocketChannel.open();
+ sc.connect(ssc.socket().getLocalSocketAddress());
+ sc.finishConnect();
+
+ // Switch to non-blocking so we can use a Selector.
+ sc.configureBlocking(false);
+
+ // Have the 'server' write something.
+ ssc.accept().write(ByteBuffer.allocate(128));
+
+ // At this point, the client should be able to read or write immediately.
+ // (It shouldn't be able to connect because it's already connected.)
+ SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE);
+ assertEquals(1, selector.select());
+ assertEquals(SelectionKey.OP_READ | SelectionKey.OP_WRITE, key.readyOps());
+ assertEquals(0, selector.select());
+ } finally {
+ selector.close();
+ ssc.close();
+ }
+ }
}