Call finishConnect() before try to call read(...) / write(...) when using 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.
This commit is contained in:
parent
54b1a100f4
commit
30fe2e868f
@ -613,6 +613,18 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int readyOps = k.readyOps();
|
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
|
// Also check for readOps of 0 to workaround possible JDK bug which may otherwise lead
|
||||||
// to a spin loop
|
// to a spin loop
|
||||||
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
|
if ((readyOps & (SelectionKey.OP_READ | SelectionKey.OP_ACCEPT)) != 0 || readyOps == 0) {
|
||||||
@ -626,15 +638,6 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
|||||||
// Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
|
// Call forceFlush which will also take care of clear the OP_WRITE once there is nothing left to write
|
||||||
ch.unsafe().forceFlush();
|
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) {
|
} catch (CancelledKeyException ignored) {
|
||||||
unsafe.close(unsafe.voidPromise());
|
unsafe.close(unsafe.voidPromise());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user