Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Aug 2008 22:06:42 +0200
From:      "Arie Keren" <ariek4u@gmail.com>
To:        freebsd-java@freebsd.org
Subject:   NIO Selector problem
Message-ID:  <166bb700808081306o7b9e1134s287a8f23042e1a41@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

I'm running Diablo Java(TM) SE Runtime Environment (build 1.6.0_07-b02) on
FreeBSD.
I have a problem related to Selector:

After receiving read event, I remove OP_READ from key.interestOps(), then
read the channel and then return the OP_READ to key.interestOps().
After this the selector doesn't wake up on read.

This problem can be reproduced with the attached test.
The test runs OK on Windows but Fails on FreeBSD.
Note that if you comment the lines marked with //1-3, the program runs OK
both on Windows and FreeBSD (but of course this causes to much false read
invocations).

arie

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestSelector {

    static boolean terminate;
    public static void main(String[] args) {
        try {
            new NioSelector();
            Socket socket = new Socket("127.0.0.1", 4000);
            for (int i=0; i<5; i++) {
                socket.getOutputStream().write(1);
                Thread.sleep(500);
            }
            terminate = true;
            socket.close();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println ((NioSelector.numReads == 5 ? "OK:" : "FAIL:") +
NioSelector.numReads);
    }

    public static class NioSelector implements Runnable {
        protected Selector selector;
        ServerSocketChannel tcpListener;
        SocketChannel tcpClient;
        ExecutorService executor;
        static int numReads;

        public NioSelector() throws IOException {
            executor = Executors.newFixedThreadPool(1);
            selector = Selector.open();
            tcpListener = ServerSocketChannel.open();
            tcpListener.configureBlocking(false);
            tcpListener.socket().bind(new InetSocketAddress(4000));
            tcpListener.register(selector, SelectionKey.OP_ACCEPT);
            new Thread(this).start();
        }

        @Override
        public void run() {
            while (!terminate) {
                try {
                    int numKeys = selector.select(1000);
                    if (numKeys == 0) continue;

                    Iterator<SelectionKey> it =
selector.selectedKeys().iterator();
                    while (it.hasNext()) {
                        SelectionKey key = it.next();
                        it.remove();

                        if (key.isAcceptable()) {
                            tcpClient =
((ServerSocketChannel)key.channel()).accept();
                            tcpClient.configureBlocking(false);
                            tcpClient.register(selector,
SelectionKey.OP_READ);
                        }
                        else if (key.isReadable()) {
                            key.interestOps(key.interestOps() &
~SelectionKey.OP_READ);  //1
                            final SelectionKey fkey = key;
                            executor.execute(new Runnable () {
                                public void run() {
                                    ByteBuffer inBuf =
ByteBuffer.allocate(1);
                                    try {
                                        if (tcpClient.read(inBuf) > 0)
numReads++;
                                    } catch (IOException e) {
                                        e.printStackTrace();
                                    }
                                    fkey.interestOps(fkey.interestOps() |
SelectionKey.OP_READ);  //2
                                    selector.wakeup();   //3
                                }
                            });
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
            executor.shutdownNow();
        }
    }

}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?166bb700808081306o7b9e1134s287a8f23042e1a41>