Search code examples
linuxepoll

POLLHUP vs. POLLRDHUP?


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?


Solution

  • 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.