diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java index 46ecd3c6e45e..a543749aa295 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollChannel.java @@ -99,12 +99,14 @@ public ChannelMetadata metadata() { @Override protected void doClose() throws Exception { active = false; - - // deregister from epoll now - doDeregister(); - - FileDescriptor fd = fileDescriptor; - fd.close(); + try { + // deregister from epoll now + doDeregister(); + } finally { + // Ensure the file descriptor is closed in all cases. + FileDescriptor fd = fileDescriptor; + fd.close(); + } } @Override diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java index 17bc9df5be76..3f8363da59ab 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/AbstractEpollStreamChannel.java @@ -765,11 +765,14 @@ private boolean doFinishConnect() throws Exception { @Override void epollRdHupReady() { - // Just call closeOnRead(). There is no need to trigger a read as this - // will result in an IOException anyway. - // - // See https://github.com/netty/netty/issues/3539 - closeOnRead(pipeline()); + if (isActive()) { + // If it is still active, we need to call epollInReady as otherwise we may miss to + // read pending data from the underyling file descriptor. + // See https://github.com/netty/netty/issues/3709 + epollInReady(); + } else { + closeOnRead(pipeline()); + } } @Override diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollEventLoop.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollEventLoop.java index ed30d5823eb1..c8d6d50c2d1f 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollEventLoop.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollEventLoop.java @@ -310,14 +310,15 @@ private void processReady(EpollEventArray events, int ready) { final long ev = events.events(i); AbstractEpollChannel ch = channels.get(fd); - if (ch != null && ch.isOpen()) { - + if (ch != null) { AbstractEpollUnsafe unsafe = (AbstractEpollUnsafe) ch.unsafe(); - // We need to check if the channel is still open before try to trigger the - // callbacks. - // See https://github.com/netty/netty/issues/3443 - if ((ev & Native.EPOLLRDHUP) != 0 && ch.isOpen()) { + // First check if EPOLLIN was set, in this case we do not need to check for + // EPOLLRDHUP as EPOLLIN will handle connection-reset case as well. + if ((ev & Native.EPOLLIN) != 0) { + // Something is ready to read, so consume it now + unsafe.epollInReady(); + } else if ((ev & Native.EPOLLRDHUP) != 0) { unsafe.epollRdHupReady(); } @@ -325,11 +326,6 @@ private void processReady(EpollEventArray events, int ready) { // force flush of data as the epoll is writable again unsafe.epollOutReady(); } - - if ((ev & Native.EPOLLIN) != 0 && ch.isOpen()) { - // Something is ready to read, so consume it now - unsafe.epollInReady(); - } } else { // We received an event for an fd which we not use anymore. Remove it from the epoll_event set. try {