2015-10-06 228 views
0

当第二个参数= 0调用eventfd_write()时,epoll_wait()永远不会返回,但当参数设置为1时。epoll_wait()返回。eventfd_write()与第二个参数= 0不起作用?

这是我如何重现: ./bug 0

它永远不会返回。

./bug 1

它返回。

下面是代码:

#include <sys/epoll.h> 
#include <sys/eventfd.h> 
#include <assert.h> 
#include <cstdlib> 
#include <iostream> 

int value = 0; 
int efd = 0; 

void* start(void* p) { 
    std::cout << __PRETTY_FUNCTION__ << ": going to sleep for 5 sec" << std::endl; 
    sleep(5); 
    std::cout << __PRETTY_FUNCTION__ << ": going to call eventfd_write() with value=" << value << std::endl; 
    const int rc = eventfd_write(efd, value); 
    assert(0 == rc); 
    return NULL; 
} 

int main(int argc, char** argv) { 
    const int epFD = epoll_create1(0); 
    assert(-1 != epFD); 

    efd = eventfd(0, 0); 
    assert(-1 != efd); 

    struct epoll_event event; 
    event.data.fd = efd; 
    event.events = EPOLLIN; 
    epoll_ctl(epFD, EPOLL_CTL_ADD, efd, &event); 

    value = strtoul(argv[1], NULL, 10); 

    const uint32_t nEvents = 2; 
    struct epoll_event events[nEvents]; 

    pthread_t threadID; 
    const int rc = pthread_create(&threadID, NULL, &start, NULL); 
    assert(0 == rc); 

    sleep(1); 

    std::cout << __PRETTY_FUNCTION__ << ": going to wait for event" << std::endl; 

    int n = epoll_wait(epFD, events, nEvents, -1); 
    assert(n > 0); 

    std::cout << "okay" << std::endl; 

    return 0; 
} 

这是我如何编译:

g++ -Wall bug.cpp -o bug -O3 -lpthread 

这里是我的glibc的版本:

$ rpm -qa | grep glibc 
glibc-common-2.12-1.107.el6.x86_64 
glibc-static-2.12-1.107.el6.x86_64 
glibc-headers-2.12-1.107.el6.x86_64 
glibc-2.12-1.107.el6.x86_64 
glibc-devel-2.12-1.107.el6.x86_64 

这里是我的G ++版本:

$ g++ --version 
g++ (GCC) 4.6.2 20111027 (Red Hat 4.6.2-1) 
Copyright (C) 2011 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

有什么想法?

回答

2

短的答案: 阅读documentation

较长答案: “写入(2)调用添加在其缓冲器中的计数器提供的8字节整数值”

“的文件描述符是如果计数器的值大于0,则可读(select(2)readfds参数; poll(2)POLLIN标志)。

因此,写入0不会向计数器添加任何内容,值为0意味着等待的文件描述符尚未准备就绪。任何非零值都可以工作(保留的0xffffffff除外)。

+0

是。想象一下,当我投射到uint64_t的指针和填充写入电话的指针不断出现时,我感到很惊讶。如果我之前读过文档而不是之后,可以节省一些调试时间。 – user4581301

+0

@dave谢谢您剪下相关的段落。我没想到用户需要知道实现 - “write(2)调用将其缓冲区中提供的8字节整数值添加到计数器”。这是一个非常有趣的实现。非常感谢您的帮助! – Hei