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
f8f1efc3ba
commit
096a605f30
@ -17,6 +17,7 @@ package io.netty.channel.nio;
|
|||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelException;
|
import io.netty.channel.ChannelException;
|
||||||
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.channel.EventLoopException;
|
import io.netty.channel.EventLoopException;
|
||||||
import io.netty.channel.SelectStrategy;
|
import io.netty.channel.SelectStrategy;
|
||||||
import io.netty.channel.SingleThreadEventLoop;
|
import io.netty.channel.SingleThreadEventLoop;
|
||||||
@ -512,9 +513,25 @@ public final class NioEventLoop extends SingleThreadEventLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
|
private void processSelectedKey(SelectionKey k, AbstractNioChannel ch) {
|
||||||
final NioUnsafe unsafe = ch.unsafe();
|
final NioUnsafe unsafe = ch.unsafe();
|
||||||
if (!k.isValid()) {
|
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
|
// close the channel if the key is not valid anymore
|
||||||
unsafe.close(unsafe.voidPromise());
|
unsafe.close(unsafe.voidPromise());
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user