According to the poll man page, the poll function can return POLLHUP and POLLRDHUP events. From what I understand, only POLLHUP is POSIX compliant, and POLLRDHUP is a Linux non-standard extension. Howerver, both seem to signal that the write end of a connection is closed, so I don't understand the added value of POLLRDHUP over POLLHUP. Would someone please explain the difference between the two?
No, when poll()
ing a socket, POLLHUP
will signal that the connection was closed in both directions.
POLLRDHUP
will be set when the other end has called shutdown(SHUT_WR)
or when this end has called shutdown(SHUT_RD)
, but the connection may still be alive in the other direction.
You can have a look at net/ipv4/tcp.c
the kernel source:
if (sk->sk_shutdown == SHUTDOWN_MASK || state == TCP_CLOSE)
mask |= EPOLLHUP;
if (sk->sk_shutdown & RCV_SHUTDOWN)
mask |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP;
SHUTDOWN_MASK
is RCV_SHUTDOWN|SEND_SHUTDOWN
. RCV_SHUTDOWN
is set when a FIN
packet is received, and SEND_SHUTDOWN
is set when a FIN
packet is acknowledged by the other end, and the socket moves to the FIN-WAIT2
state.
[except for the TCP_CLOSE
part, that snippet is replicated by all protocols; and the whole thing works similarly for unix sockets, etc]
There are other important differences -- POLLRDHUP
(unlike POLLHUP
) has to be set explicitly in .events
in order to be returned in .revents
.
And POLLRDHUP
only works on sockets, not on fifos/pipes or ttys.
© 2022 - 2025 — McMap. All rights reserved.
POLLRDHUP
. Although for TCP, I don't see how the two events can be distinguished. TCP doesn't send any indication when the remote socket has closed for reading, only when it closes for writing. – ApteryxSEND_SHUTDOWN
flag on the local socket. Please refer to thenet/ipv4/tcp_input.c
file in the kernel source. When thePOLLRDHUP
flag is set inrevents
but notPOLLHUP
, the socket is half-closed: you can still write but not read from it. – Adventurism