NioEventLoop closes channel even if channel is not registered
Motivation: If a channel is deregistered from an NioEventLoop the associated SelectionKey is cancelled. If the NioEventLoop has yet to process a pending event as a result of that SelectionKey then the NioEventLoop will see the SelecitonKey is invalid and close the channel. The NioEventLoop should not close a channel if it is not registered with that NioEventLoop. Modifications: - NioEventLoop.processSelectedKeys should check that the channel is still registered to itself before closing the channel Result: NioEventLoop doesn't close a channel that is no longer registered to it when the SelectionKey is invalid Fixes https://github.com/netty/netty/issues/5125
This commit is contained in:
parent
f60698a538
commit
04e33fd2d8
@ -17,6 +17,7 @@ package io.netty.channel.nio;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelException;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.EventLoopException;
|
||||
import io.netty.channel.SelectStrategy;
|
||||
import io.netty.channel.SingleThreadEventLoop;
|
||||
@ -511,9 +512,25 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
||||
}
|
||||
}
|
||||
|
||||
private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
|
||||
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
|
||||
final AbstractNioChannel.NioUnsafe unsafe = ch.unsafe();
|
||||
if (!k.isValid()) {
|
||||
final EventLoop eventLoop;
|
||||
try {
|
||||
eventLoop = ch.eventLoop();
|
||||
} catch (Throwable ignored) {
|
||||
// If the channel implementation throws an exception because there is no event loop, we ignore this
|
||||
// because we are only trying to determine if ch is registered to this event loop and thus has authority
|
||||
// to close ch.
|
||||
return;
|
||||
}
|
||||
// Only close ch if ch is still registerd to this EventLoop. ch could have deregistered from the event loop
|
||||
// and thus the SelectionKey could be cancelled as part of the deregistration process, but the channel is
|
||||
// still healthy and should not be closed.
|
||||
// See https://github.com/netty/netty/issues/5125
|
||||
if (eventLoop != this || eventLoop == null) {
|
||||
return;
|
||||
}
|
||||
// close the channel if the key is not valid anymore
|
||||
unsafe.close(unsafe.voidPromise());
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user