epoll_wait似乎陷入了EPOLLRDHUP

时间:2017-10-13 14:59:04

标签: linux sockets network-programming epoll

所以我有一些看起来像这样的代码:

for (;;) {
        errno=0;
        epoll_event e = {};
        auto wait_r = epoll_wait(g.epoll_fd, &e, 1, 0);
        if (wait_r==0) break;
        if(wait_r ==-1 && errno==EINTR) {
            printf("got EINTR\n");
            continue;
        }
        assert(wait_r == 1);

        auto& c = *(Context*)e.data.ptr;

        if(e.events & EPOLLERR ) {

            int       error = 0;
            socklen_t errlen = sizeof(error);
            auto r1 =getsockopt(c.socket, SOL_SOCKET, SO_ERROR, (void *)&error, &errlen);
            assert(r1==0);
            printf("Got EPOLLERR 2 %s\n", strerror(error));
        }


        if(e.events & EPOLLRDHUP || e.events & EPOLLHUP ) {
            if (e.events & EPOLLRDHUP) {
                printf("got to EPOLLRDHUP\n");
            }
            if (e.events & EPOLLHUP) {
                printf("got to EPOLLHUP\n");
            }
            //continue; // keeps hitting this for same connections
            break;
        }

        if (e.events & EPOLLIN) {

            // Does a bunch of reads...
        }
    }
}

单个套接字将卡在EPOLLRDHUP || EPOLLHUP案例中。套接字可能已关闭,当我尝试关闭它或执行EPOLL_CTL_DEL时,我得到一个EBADFD。据我了解,epoll将自动摆脱任何死插座,但这似乎并非如此......任何想法?

另一个可能的问题是在套接字上我使用recvmsg / sendmsg并且我在进程之间通过这些套接字发送文件描述符,这些套接字是unix域流套接字。我试图对它做一个最终的recvmsg,但那也失败了......任何想法?

1 个答案:

答案 0 :(得分:0)

对于我的问题,解决方案是改变这样的一行:

c.socket = accept(g.server_socket, NULL, NULL);

到此:

c.socket = accept4(g.server_socket, NULL, NULL, SOCK_CLOEXEC);

如果其他人遇到此问题,请留意dup()exec()来电。即使您已经关闭了添加到dup()的fd,epoll也可能导致epoll表现得没有关闭。只有当fd的所有副本都关闭时,epoll才会认出它已关闭。对于您使用exec()标志创建的每个fd,dup()基本上都会与SOCK_CLOEXEC做同样的事情......