Skip to content

Commit

Permalink
Call finishConnect() before try to call read(...) / write(...) when u…
Browse files Browse the repository at this point in the history
…sing NIO

Motivation:

The JDK implementation of SocketChannel has an internal state that is tracked for its operations. Because of this we need to ensure we call finishConnect() before try to call read(...) / write(...) as otherwise it may produce a NotYetConnectedException.

Modifications:

First process OP_CONNECT flag.

Result:

No more possibility of NotYetConnectedException because OP_CONNECT is handled not early enough when processing interestedOps for a Channel.
  • Loading branch information
normanmaurer committed Sep 1, 2016
1 parent 54b1a10 commit 30fe2e8
Showing 1 changed file with 12 additions and 9 deletions.
21 changes: 12 additions & 9 deletions transport/src/main/java/io/netty/channel/nio/NioEventLoop.java
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,18 @@ private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {

try {
int readyOps = k.readyOps();
// We first need to call finishConnect() before try to trigger a read(...) or write(...) as otherwise
// the NIO JDK channel implementation may throw a NotYetConnectedException.
if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
// remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
// See https://github.com/netty/netty/issues/924
int ops = k.interestOps();
ops &= ~SelectionKey.OP_CONNECT;
k.interestOps(ops);

unsafe.finishConnect();
}

// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
// to a spin loop
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
Expand All @@ -626,15 +638,6 @@ private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
// Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
ch.unsafe().forceFlush();
}
if ((readyOps & SelectionKey.OP_CONNECT) != 0) {
// remove OP_CONNECT as otherwise Selector.select(..) will always return without blocking
// See https://github.com/netty/netty/issues/924
int ops = k.interestOps();
ops &= ~SelectionKey.OP_CONNECT;
k.interestOps(ops);

unsafe.finishConnect();
}
} catch (CancelledKeyException ignored) {
unsafe.close(unsafe.voidPromise());
}
Expand Down

0 comments on commit 30fe2e8

Please sign in to comment.