POLLHUP vs. POLLRDHUP?
Asked Answered
H

1

8

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?

Henton answered 16/5, 2019 at 21:52 Comment(9)
It means the remote end did a partial shutdown of the socket and won't be sending any more data but can still receive.Organology
@Organology When you say "it", do you mean POLLHUP but not POLLRDHUP? Or POLLRDHUP but not POLLHUP? Or do you mean they both mean this? Or what?Betide
"it" is the added value of 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.Apteryx
@Shawn, Would POLLRDHUP ever be set for a file descriptor representing a FIFO?Henton
@Apteryx The indication that the remove socket has closed for reading is that it has acknoledged our FIN packet.Adventurism
@Henton no, POLLRDHUP will not be set for a FIFO.Adventurism
@mosvy That's not true. The ACK just indicates that the FIN was received and the socket is still open. But you can't tell the difference between fully open and half-closed.Apteryx
@Apteryx What's "not true"? That's how it works in Linux. When the remote end has acked the FIN, the kernel with turn the SEND_SHUTDOWN flag on the local socket. Please refer to the net/ipv4/tcp_input.c file in the kernel source. When the POLLRDHUP flag is set in revents but not POLLHUP, the socket is half-closed: you can still write but not read from it.Adventurism
@mosvy I don't dispute that the receiver of the ACK does this, but I don't see how the ACK means that the remote end has half-closed the socket.Apteryx
A
10

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.

Adventurism answered 19/5, 2019 at 9:23 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.