From 631077c79391fde22afdb1e43d0f642ba530101e Mon Sep 17 00:00:00 2001 From: Scott Mitchell Date: Sat, 7 Jan 2017 01:04:29 -0800 Subject: [PATCH] EPOLL RDHUP processing Motivation: EpollRecvByteAllocatorHandle will read unconditionally if EPOLLRDHUP has been received. However we can just treat this the same was we do as data maybe pending in ET mode, and let LT mode notify us if we haven't read all data. Modifications: - EpollRecvByteAllocatorHandle should not always force a read just because EPOLLRDHUP has been received, but just treated as an indicator that there maybe more data to read in ET mode Result: Fixes https://github.com/netty/netty/issues/6173. --- .../channel/epoll/EpollRecvByteAllocatorHandle.java | 11 +++++++---- .../epoll/EpollRecvByteAllocatorStreamingHandle.java | 4 +++- 2 files changed, 10 insertions(+), 5 deletions(-) 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()); } }