diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorHandle.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorHandle.java index b79bba527c..e33b42ce99 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorHandle.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorHandle.java @@ -32,8 +32,13 @@ class EpollRecvByteAllocatorHandle extends RecvByteBufAllocator.DelegatingHandle receivedRdHup = true; } + final boolean isReceivedRdHup() { + return receivedRdHup; + } + boolean maybeMoreDataToRead() { - return isEdgeTriggered && lastBytesRead() > 0; + // If EPOLLRDHUP has been received we must read until we get a read error. + return isEdgeTriggered && (lastBytesRead() > 0 || receivedRdHup); } final void edgeTriggered(boolean edgeTriggered) { @@ -53,9 +58,7 @@ class EpollRecvByteAllocatorHandle extends RecvByteBufAllocator.DelegatingHandle * continue to avoid a {@link StackOverflowError} between channelReadComplete and reading from the * channel. It is expected that the {@link #EpollSocketChannel} implementations will track if we are in * edgeTriggered mode and all data was not read, and will force a EPOLLIN ready event. - * - * If EPOLLRDHUP has been received we must read until we get a read error. */ - return receivedRdHup || maybeMoreDataToRead() && config.isAutoRead() || super.continueReading(); + return maybeMoreDataToRead() && config.isAutoRead() || super.continueReading(); } } diff --git a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorStreamingHandle.java b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorStreamingHandle.java index 9746e74248..393ab41e6f 100644 --- a/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorStreamingHandle.java +++ b/transport-native-epoll/src/main/java/io/netty/channel/epoll/EpollRecvByteAllocatorStreamingHandle.java @@ -28,7 +28,9 @@ final class EpollRecvByteAllocatorStreamingHandle extends EpollRecvByteAllocator /** * For stream oriented descriptors we can assume we are done reading if the last read attempt didn't produce * a full buffer (see Q9 in epoll man). + * + * If EPOLLRDHUP has been received we must read until we get a read error. */ - return isEdgeTriggered() && lastBytesRead() == attemptedBytesRead(); + return isEdgeTriggered() && (lastBytesRead() == attemptedBytesRead() || isReceivedRdHup()); } }