Fix SelectableChannel support in NioEventLoop (#8344)

Motivation:

Unless the 'io.netty.noKeySetOptimization' system property is set,
registering a SelectableChannel instance to a NioEventLoop results
in a ClassCastException:

    io.netty.channel.nio.SelectedSelectionKeySetSelector cannot be cast
        to java.nio.channels.spi.AbstractSelector

Modifications:

Instead of 'selector', pass 'unwrappedSelector' to SelectableChannel.

Result:

It is possible to register a SelectableChannel instance without
setting the 'io.netty.noKeySetOptimization' system property.
This commit is contained in:
Jussi Virtanen 2018-10-09 05:11:07 +01:00 committed by Norman Maurer
parent 6cebb6069b
commit fc28bccdf1
2 changed files with 40 additions and 1 deletions

View File

@ -294,7 +294,7 @@ public final class NioEventLoop extends SingleThreadEventLoop {
}
try {
ch.register(selector, interestOps, task);
ch.register(unwrappedSelector, interestOps, task);
} catch (Exception e) {
throw new EventLoopException("failed to register a channel", e);
}

View File

@ -24,7 +24,10 @@ import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.Future;
import org.junit.Test;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -132,4 +135,40 @@ public class NioEventLoopTest extends AbstractEventLoopTest {
group.shutdownGracefully();
}
}
@Test(timeout = 1000)
public void testSelectableChannel() throws Exception {
NioEventLoopGroup group = new NioEventLoopGroup(1);
NioEventLoop loop = (NioEventLoop) group.next();
try {
Channel channel = new NioServerSocketChannel();
loop.register(channel).syncUninterruptibly();
channel.bind(new InetSocketAddress(0)).syncUninterruptibly();
SocketChannel selectableChannel = SocketChannel.open();
selectableChannel.configureBlocking(false);
selectableChannel.connect(channel.localAddress());
final CountDownLatch latch = new CountDownLatch(1);
loop.register(selectableChannel, SelectionKey.OP_CONNECT, new NioTask<SocketChannel>() {
@Override
public void channelReady(SocketChannel ch, SelectionKey key) {
latch.countDown();
}
@Override
public void channelUnregistered(SocketChannel ch, Throwable cause) {
}
});
latch.await();
selectableChannel.close();
channel.close().syncUninterruptibly();
} finally {
group.shutdownGracefully();
}
}
}