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

(se) NIO selector wakes up with 0 selected keys infinitely [lnx 2.4]

    Details

    • Type: Bug
    • Status: Closed
    • Priority: P4
    • Resolution: Won't Fix
    • Affects Version/s: 6
    • Fix Version/s: None
    • Component/s: core-libs
    • Labels:
    • Subcomponent:
    • CPU:
      x86
    • OS:
      linux

      Description

      FULL PRODUCT VERSION :
      java version "1.6.0_03"
      Java(TM) SE Runtime Environment (build 1.6.0_03-b05)
      Java HotSpot(TM) Server VM (build 1.6.0_03-b05, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      1. Linux hostname 2.4.21-27.ELsmp #1 SMP Wed Dec 1 21:59:02 EST 2004 i686 i686 i386 GNU/Linux

      2. HP-UX hostname2 B.11.23 U ia64 2718609364 unlimited-user license


      A DESCRIPTION OF THE PROBLEM :
      The NIO selector wakes up infinitely in this situation..

      0. server waits for connection
      1. client connects and write message
      2. server accepts and register OP_READ
      3. server reads message and remove OP_READ from interest op set
      4. client close the connection
      5. server write message (without any reading.. surely OP_READ is not set)
      6. server's select wakes up infinitely with return value 0


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      First run the TestServer.
       java -cp . TestServer 7777

      In another console, run the TestClient
       java -cp . TestClient 192.168.1.34 7777



      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      I expected nothing will happen (the selector should not woke up).

      ACTUAL -
      In windows, it worked as I expected but, in Linux and HP/UX the selector goes into the infinite loop.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      TestServer.java

      import java.io.*;
      import java.net.*;
      import java.nio.*;
      import java.nio.channels.*;
      import java.nio.charset.*;
      import java.util.*;
      import java.util.logging.*;

      public class TestServer {
          private static final long SLEEP_PERIOD = 5000L; // 5 seconds
          private static final int BUFFER_SIZE = 8192;
          private int port;

          public TestServer(int port) {
              this.port = port;
          }

          public static void main(String[] args) throws Throwable {
      if (args.length < 1) {
      System.err.println("Usage : java TestServer <port>");
      System.exit(0);
      }

              new TestServer(Integer.parseInt(args[0])).start();
          }

          public void start() throws Throwable {
      ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);

              ServerSocketChannel serverChannel = ServerSocketChannel.open();
              serverChannel.configureBlocking(false);
              ServerSocket server = serverChannel.socket();
              server.bind(new InetSocketAddress(port));

              Selector selector = Selector.open();
              serverChannel.register(selector, SelectionKey.OP_ACCEPT);
              SocketChannel clientChannel = null;

              System.out.println("0. SERVER STARTED TO LISTEN");
              boolean writeNow = false;

      while (true) {
      try {
      // wait for selection
      int numKeys = selector.select();

                      if (numKeys == 0) {
                          System.err.println("select wakes up with zero!!!");
                      }

      Iterator it = selector.selectedKeys().iterator();
      while (it.hasNext()) {
      SelectionKey selected = (SelectionKey) it.next();
      int ops = selected.interestOps();

                          try {
                              // process new connection
                              if ((ops & SelectionKey.OP_ACCEPT) != 0) {
                                  clientChannel = serverChannel.accept();
                                  clientChannel.configureBlocking(false);

                                  // register channel to selector
                                  clientChannel.register(selector, SelectionKey.OP_READ, null);
                                  System.out.println("2. SERVER ACCEPTED AND REGISTER READ OP : client - " + clientChannel.socket().getInetAddress());
                              }

                              if ((ops & SelectionKey.OP_READ) != 0) {
                                  // read client message
                                  System.out.println("3. SERVER READ DATA FROM client - " + clientChannel.socket().getInetAddress());
                                  readClient((SocketChannel) selected.channel(), buffer);

                                  // deregister OP_READ
                                  System.out.println("PREV SET : " + selected.interestOps());
                                  selected.interestOps(selected.interestOps() & ~SelectionKey.OP_READ);
                                  System.out.println("NEW SET : " + selected.interestOps());

                                  Thread.sleep(SLEEP_PERIOD * 2);
                                  new WriterThread(clientChannel).start();
                              }

                          } finally {
                              // remove from selected key set
                              it.remove();
                          }
      }
      } catch (IOException e) {
      System.err.println("IO Error : " + e.getMessage());
      }
      }
          }


          public void readClient(SocketChannel channel, ByteBuffer buffer) throws IOException {
              try {
                  buffer.clear();

                  int nRead = channel.read(buffer);

                  if (nRead < 0) {
                      channel.close();
                      return;
                  }

                  if (buffer.position() != 0) {
                      int size = buffer.position();
                      buffer.flip();
                      byte[] bytes = new byte[size];
                      buffer.get(bytes);
                      System.out.println("RECVED : " + new String(bytes));
                  }
              } catch (IOException e) {
                  System.err.println("IO Error : " + e.getMessage());
                  channel.close();
              }
          }

          static class WriterThread extends Thread {
              private SocketChannel clientChannel;
              public WriterThread(SocketChannel clientChannel) {
                  this.clientChannel = clientChannel;
              }

              public void run() {
                  try {
                      writeClient(clientChannel);
                      System.out.println("5. SERVER WRITE DATA TO client - " + clientChannel.socket().getInetAddress());
                  } catch (IOException e) {
                      System.err.println("5. SERVER WRITE DATA FAILED : " + e);
                  }
              }

              public void writeClient(SocketChannel channel) throws IOException {
                  try {
                      ByteBuffer buffer = ByteBuffer.wrap("zwxydfdssdfsd".getBytes());
                      int total = buffer.limit();

                      int totalWrote = 0;
                      int nWrote = 0;

                      while ((nWrote = channel.write(buffer)) >= 0) {
                          totalWrote += nWrote;
                          if (totalWrote == total) {
                              break;
                          }
                      }
                  } catch (IOException e) {
                      System.err.println("IO Error : " + e.getMessage());
                      channel.close();
                  }
              }


          }
      }


      TestClient.java

      import java.util.logging.*;
      import java.io.*;
      import java.net.*;

      public class TestClient {
          private static final long SLEEP_PERIOD = 5000L; // 5 seconds
          private String host;
          private int port;

          public TestClient(String host, int port) {
              this.host = host;
              this.port = port;
          }

          public static void main(String[] args) throws Throwable {
      if (args.length < 2 || args[0].equals("127.0.0.1") || args[0].equals("localhost")) {
      System.err.println("Usage : java TestClient <host name> <port> (host name should not be localhost)");
      System.exit(0);
      }

              new TestClient(args[0], Integer.parseInt(args[1])).start();
          }

          public void start() throws Throwable {
              Socket socket = new Socket(host, port);

      BufferedReader in = new BufferedReader(
      new InputStreamReader(socket.getInputStream()));
      PrintWriter out = new PrintWriter(
      new OutputStreamWriter(socket.getOutputStream()),
      true /* auto flush */);

              out.println("abcdef");

              System.out.println("1. CLIENT CONNECTED AND WROTE MESSAGE");

              Thread.sleep(SLEEP_PERIOD);

      // socket.shutdownOutput();
              socket.close();

              System.out.println("4. CLIENT SHUTDOWN OUTPUT");

              Thread.sleep(SLEEP_PERIOD * 3);
          }
      }


      ---------- END SOURCE ----------

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                Unassigned
                Reporter:
                ndcosta Nelson Dcosta (Inactive)
              • Votes:
                0 Vote for this issue
                Watchers:
                0 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved:
                  Imported:
                  Indexed: