1

I have the following code. And you can see its output below. As I think by javadoc socket.read should never hang or whatever and this is an unexpected behavior.

    Context con = new Context();
    con.buf = ByteBuffer.allocate(1024);
    log.trace("reading.. {}, {}, {}, {}, {}", socket.isConnected(), !socket.isBlocking(), socket.isOpen(), socket.keyFor(selector).isReadable(), socket.keyFor(selector).isValid());

    FutureTask<Integer> readTask = new FutureTask<Integer>(

            new Callable<Integer>() {

                Context con;

                Callable<Integer> setContext(Context con) {
                    this.con = con;
                    return this;
                }

                public Integer call() throws Exception{
                    int rd = socket.read(con.buf);
                    return Integer.valueOf(rd);
                }

            }.setContext(con)
    );

    ExecutorService exec = Executors.newSingleThreadExecutor();
    exec.submit(readTask);

    int read = 0;
    try {
        read = readTask.get(5, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException | TimeoutException e) {
        log.error("hello java");
        System.exit(0);
    }

(I do not need a futuretask there at all, but it was just to check my assumption about stucking in socket.read method).

And here's the log output (notice that !socket.isBlocking() is reversed, so it's showing it's in NON blocking mode):

reading.. true, true, true, true, true
hello java 

this means after 5 seconds we still got nothing, socket is still opened, and nothing that could be wrong.

Please help me with that issue. Could it be something around socket's "keepalive" or OS or java or firewall (still I'm reading and writing at localhost only) issue?

This is how I got this socket:

SocketChannel socket = ((ServerSocketChannel) key.channel()).accept();
log.trace("accepted:{}", socket.getRemoteAddress());
socket.configureBlocking(false);
socket.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
Mikhail Boyarsky
  • 2,908
  • 3
  • 22
  • 37
  • You should show where you create the socket – crocboy Jul 29 '14 at 16:53
  • I've added that to the question body. – Mikhail Boyarsky Jul 29 '14 at 16:57
  • Are you calling `read()` on this channel from anywhere else? – crocboy Jul 29 '14 at 16:58
  • On some of the channels, that were created exactly like that. – Mikhail Boyarsky Jul 29 '14 at 16:59
  • 1
    This could be your problem... From the Javadoc: If another thread has already initiated a read operation upon this channel, however, then an invocation of this method will block until the first operation is complete. – crocboy Jul 29 '14 at 17:01
  • Have you stepped through this code in a debugger? – Tim Jul 29 '14 at 17:04
  • @Tim is correct, `read()` is not even being called here – crocboy Jul 29 '14 at 17:05
  • No, I'm sorry that was the old version of code. I could either update the output with the values that println printed, but just removed printlns. It certainly does call `socket.read()`. And the issue appears only after 30-40 connected normally. – Mikhail Boyarsky Jul 29 '14 at 17:10
  • Then see my above comment about doing a `read()` from the same channel in multiple places – crocboy Jul 29 '14 at 17:13
  • @crocboy I've marked the thread name with a timestamp so I could see that there were no other thread (just to be sure, at first I knew there were no other thread) and `socket.read` is being called only there. There's no other `read` usage. May the same thread block? – Mikhail Boyarsky Jul 29 '14 at 17:21
  • I'll ask it again: "Have you stepped through this code in a debugger?" With a debugger, you should be able to see what's going on within the `socket.read()` call, which will let you see (for example) if you're getting held up by an if statement about another thread having an in-progress read, or whatever. – Tim Jul 29 '14 at 17:57
  • *Why* do you have the following code? If you want asynchronous I/O, it already exists. – user207421 Jul 29 '14 at 17:58
  • You say you see this after 30-40 successful connections. What happens to your `SocketChannel` and your `Socket` between connections? Do you reuse them, build new ones each time, etc.? – Tim Jul 29 '14 at 18:09
  • @Tim in this case it's new socket channel per new client and channels are not being reused. There are 2 problems with debugging: 1) it's sun.nio.. class, so no source provided 2) my code is a part of web application on tomcat, I'm going to make a simpler version of it, without web context. – Mikhail Boyarsky Jul 29 '14 at 18:42
  • You can download OpenJDK source JARs as described here: http://stackoverflow.com/questions/2896727/where-to-find-java-jdk-source-code. If you're using [WTP](http://www.mulesoft.com/tcat/tomcat-wtp), you can debug webapps running on your local Tomcat. (WTP will also let you automatically deploy code to your local Tomcat, which is really useful during development.) – Tim Jul 29 '14 at 19:06

0 Answers0