How to handle the Linux socket revents POLLERR, POLLHUP and POLLNVAL?

后端 未结 4 780
栀梦
栀梦 2020-12-05 18:58

I\'m wondering what should be done when poll set these bits? Close socket, ignore it or what?

4条回答
  •  余生分开走
    2020-12-05 19:18

    Minimal FIFO example

    Once you understand when those conditions happen, it should be easy to know what to do with them.

    poll.c

    #define _XOPEN_SOURCE 700
    #include  /* creat, O_CREAT */
    #include  /* poll */
    #include  /* printf, puts, snprintf */
    #include  /* EXIT_FAILURE, EXIT_SUCCESS */
    #include  /* read */
    
    int main(void) {
        char buf[1024];
        int fd, n;
        short revents;
        struct pollfd pfd;
    
        fd = open("poll0.tmp", O_RDONLY | O_NONBLOCK);
        pfd.fd = fd;
        pfd.events = POLLIN;
        while (1) {
            puts("loop");
            poll(&pfd, 1, -1);
            revents = pfd.revents;
            if (revents & POLLIN) {
                n = read(pfd.fd, buf, sizeof(buf));
                printf("POLLIN n=%d buf=%.*s\n", n, n, buf);
            }
            if (revents & POLLHUP) {
                printf("POLLHUP\n");
                close(pfd.fd);
                pfd.fd *= -1;
            }
            if (revents & POLLNVAL) {
                printf("POLLNVAL\n");
            }
            if (revents & POLLERR) {
                printf("POLLERR\n");
            }
        }
    }
    

    GitHub upstream.

    Compile with:

    gcc -o poll.out -std=c99 poll.c
    

    Usage:

    sudo mknod -m 666 poll0.tmp p
    ./poll.out
    

    On another shell:

    printf a >poll0.tmp
    

    POLLHUP

    If you don't modify the source: ./poll.out outputs:

    loop
    POLLIN n=1 buf=a
    loop
    POLLHUP
    loop
    

    So:

    • POLLIN happens when input becomes available
    • POLLHUP happens when the file is closed by the printf
    • close(pfd.fd); and pfd.fd *= -1; clean things up, and we stop receiving POLLHUP
    • poll hangs forever

    This is the normal operation.

    You could now repoen the FIFO to wait for the next open, or exit the loop if you are done.

    POLLNAL

    If you comment out pfd.fd *= -1;: ./poll.out prints:

    POLLIN n=1 buf=a
    loop
    POLLHUP
    loop
    POLLNVAL
    loop
    POLLNVAL
    ...
    

    and loops forever.

    So:

    • POLLIN and POLLHUP and close happened as before
    • since we didn't set pfd.fd to a negative number, poll keeps trying to use the fd that we closed
    • this keeps returning POLLNVAL forever

    So we see that this shouldn't have happened, and indicates a bug in your code.

    POLLERR

    I don't know how to generate a POLLERR with FIFOs. Let me know if there is way. But it should be possible with file_operations of a device driver.

    Tested in Ubuntu 14.04.

提交回复
热议问题