代码之家  ›  专栏  ›  技术社区  ›  Aftermathew

在命名管道(fifo)上使用poll()时,看起来OSX确实有一个bug。专家能确认吗?

  •  3
  • Aftermathew  · 技术社区  · 16 年前

    有一段时间,我一直在尝试从一组命名管道中进行轮询,并且一直在得到Pollnval对任何命名管道文件描述符的即时响应。找到这个之后 blog post about broken polling in OS X 我很确定这是OS X中的B-U-G错误。

    我已经计划将我的代码转换为使用UDP套接字,但我想请So验证这一点a)以便我确定它确实已损坏,b)用于文档目的。

    下面是我编写的代码的简化版本(尽管我测试的上面链接中的代码拼写得很好):

    #includes
    ...
    ....
    #
    
    static const char* first_fifo_path = "/tmp/fifo1";
    static const char* second_fifo_path = "/tmp/fifo2";
    
    int setup_read_fifo(const char* path){
      int fifo_fd = -1;
    
      if( mkfifo(path, S_IRWXU | S_IRWXG | S_IRWXO) )
        perror("error calling mkfifo()... already exists?\n");
    
      if((fifo_fd = open(path, O_RDONLY | O_NDELAY)) < 0)
        perror("error calling open()");
    
      return fifo_fd;
    }
    
    void do_poll(int fd1, int fd2){
      char inbuf[1024];
      int num_fds = 2;
      struct pollfd fds[num_fds];
      int timeout_msecs = 500;
    
      fds[0].fd = fd1;
      fds[1].fd = fd2;
      fds[0].events = POLLIN;
      fds[1].events = POLLIN;
    
      int ret;
      while((ret = poll(fds, num_fds, timeout_msecs)) >= 0){
        if(ret < 0){
          printf("Error occured when polling\n");
          printf("ret %d, errno %d\n", ret, errno);
          printf("revents =  %xh : %xh \n\n", fds[0].revents, fds[1].revents);
        }
    
       if(ret == 0){
          printf("Timeout Occurred\n");
          continue;
        }                                                                   
    
        for(int i = 0; i< num_fds; i++){
          if(int event = fds[i].revents){
    
            if(event & POLLHUP)
              printf("Pollhup\n");
            if(event & POLLERR)
              printf("POLLERR\n");
            if(event & POLLNVAL)
              printf("POLLNVAL\n");
    
            if(event & POLLIN){
              read(fds[i].fd, inbuf, sizeof(inbuf));
              printf("Received: %s", inbuf);
            }
          }
        }
      }
    }
    
    int main (int argc, char * const argv[]) {
      do_poll(setup_read_fifo(first_fifo_path), setup_read_fifo(second_fifo_path));
      return 0;
    }
    

    此输出:

    $ ./executive 
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    POLLNVAL
    ...
    

    令人作呕

    还有人碰到这个吗?这是一个真正的错误,对吗?

    3 回复  |  直到 13 年前
        1
  •  3
  •   dwc    16 年前

    这似乎是一个真正的错误。它在Linux和OpenBSD上按预期工作,并像您在OSX上描述的那样失败。

        2
  •  3
  •   Mart Oruaas    16 年前

    OSX 10.4.1,我可以确认行为。在Linux上,相同的代码可以正常工作(只要超时消息正常)。所有的证据,包括这个- http://www.virtualbox.de/changeset/12347 -表明存在一个真正的问题。

        3
  •  1
  •   vasi    16 年前

    是的,已知的错误。我认为投票破裂是10.4年后的事了,我们必须在芬克处理。glib的configure.in对此进行了测试,因此您可以确定您没有想象它。(好吧,不完全是这样,在设备而不是FIFOS上对轮询进行glib测试。)