Commits

Anonymous committed 131dcd1 Merge

Merge "Fix Selector to allow read and write at the same time."

Comments (0)

Files changed (2)

luni/src/main/java/java/nio/SelectorImpl.java

             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;
                 }

luni/src/test/java/libcore/java/nio/channels/SelectorTest.java

 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;
         }
     }
 
-    /**
-     * 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();
+      }
+    }
 }