Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4744052

AbstractSelectableChannel.implCloseChannel does not check entire key array

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P2 P2
    • 1.4.2
    • 1.4.1
    • core-libs
    • mantis
    • sparc
    • solaris_8
    • Verified



      Name: nt126004 Date: 09/09/2002


      FULL PRODUCT VERSION :
      java version "1.4.1-rc"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-rc-b19)
      Java HotSpot(TM) Client VM (build 1.4.1-rc-b19, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      SunOS darden 5.8 Generic_108528-06 sun4u sparc SUNW,Ultra-5_10

      ADDITIONAL OPERATING SYSTEMS :
      Linux mango 2.4.7-10 #1 Thu Sep 6 17:27:27 EDT 2001 i686
      unknown



      A DESCRIPTION OF THE PROBLEM :
      When implCloseChannel() is called in
      AbstractSelectableChannel not all the keys are canceled,
      which keeps the connection from closing.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Register a SelectableChannel with Selector A.
      2. Register the same channel with Selector B.
      3. Cancel the channel's key from Selector A.
      4. Close the channel.

      This seems to be the result of the following code in
      AbstractSelectableChannel:
      protected final void implCloseChannel() throws IOException {
      implCloseSelectableChannel();
          synchronized (keyLock) {
              for (int i = 0; i < keyCount; i++) {
                  SelectionKey k = keys[i];
                  if (k != null)
                  k.cancel();
              }
          }
      }

      keyCount should be keys.length

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected results are that both selectors will contain zero
      SelectableKeys and the channel will be closed. Actual
      result is that the channel is still open and the key is
      still in SelectorB.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.nio.*;
      import java.nio.channels.*;

      import java.net.*;
      import java.util.*;

      public class MultiSelectorTestServer {

          private static ServerSocketChannel ssc;
          private static Selector connectSelector;
          private static Selector selectorA;
          private static Selector selectorB;

          public static void main(String args[]) {

              InetSocketAddress address = new InetSocketAddress(8888);

              try {
                  connectSelector = Selector.open();
                  selectorA = Selector.open();
                  selectorB = Selector.open();

                  ssc = ServerSocketChannel.open();
                  ssc.configureBlocking(false);
                  ssc.socket().bind(address);
                  ssc.register(connectSelector, SelectionKey.OP_ACCEPT);
                  print("Bound to " + address);
              }
              catch(Exception e) {
                  print(e);
              }

              while (true) {
                  try {
                      connectSelector.select();
                      acceptPendingConnections();
                  } catch (Exception e) {
                      print(e);
                  }
              }
          }

          private static void acceptPendingConnections() throws Exception {
                  ServerSocketChannel readyChannel;
                  SocketChannel incomingChannel;
                  Set readyKeys = connectSelector.selectedKeys();

                  for (Iterator i = readyKeys.iterator(); i.hasNext(); ) {
                      SelectionKey key = (SelectionKey) i.next();
                      i.remove();

                      readyChannel = (ServerSocketChannel) key.channel();

                      incomingChannel = readyChannel.accept();
                      incomingChannel.configureBlocking(false);
                      incomingChannel.register(selectorA, SelectionKey.OP_READ);
                      incomingChannel.register(selectorB, SelectionKey.OP_READ);

                      print("\nAccepting connection from " + incomingChannel.socket
      ());
                      print("selectorA contains " + selectorA.keys().size()+ "
      keys.");
                      print("selectorB contains " + selectorB.keys().size()+ "
      keys.");

                      print("\ncancelling key with selectorA");
                      incomingChannel.keyFor(selectorA).cancel();
                      selectorA.select(1);
                      print("selectorA contains " + selectorA.keys().size()+ "
      keys.");
                      print("selectorB contains " + selectorB.keys().size()+ "
      keys.");

                      print("\nclosing channel, both keys should be cancelled,
      connection should be closed.");
                      incomingChannel.close();
                      selectorB.select(1);
                      selectorA.select(1);
                      print("selectorA contains " + selectorA.keys().size()+ "
      keys.");
                      print("selectorB contains " + selectorB.keys().size()+ "
      keys.");
                      print("connection is open: " + incomingChannel.isOpen());
                  }
          }

          public static void print(Object obj) {
              System.out.println(obj);
          }
       }
      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      Manually remove the channel's keys with each selector
      before closing the channel.
      (Review ID: 164116)
      ======================================================================

            mmcclosksunw Michael Mccloskey (Inactive)
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: