看起来 OS X 在命名管道(FIFO)上使用 poll() 时确实有一个错误......专家可以确认吗?

发布于 2024-07-14 04:39:25 字数 2129 浏览 3 评论 0原文

我一直在尝试从一组命名管道进行轮询一段时间,并且我不断在任何命名管道文件描述符上收到 POLLNVAL 的立即响应。 在找到这篇关于 OS X 中轮询损坏的博客文章之后,我非常确定这是一个OS X 中的 bug。

我已经计划将我的代码切换为使用 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
...

令人恶心。

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

I'm been trying to poll from a set of named-pipes for a little while now and i keep getting an immediate response of POLLNVAL on any named pipe file descriptor. After finding this blog post about broken polling in OS X I'm pretty certain that this is a b-u-g bug in OS X.

I'm already planning on switching my code to using UDP sockets, but i wanted to ask SO for verification about this a) so that I'm sure it's really broken, and b) for documentation purposes.

Here is a stripped down version of the code I wrote (although the code in the link above, which I tested, spells it out pretty well):

#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;
}

this outputs:

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

ad nauseam.

Anybody else run into this? This is a real bug right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

回忆躺在深渊里 2024-07-21 04:39:25

这似乎是一个真正的错误。 它在 Linux 和 OpenBSD 上按预期工作,但在 OS X 上如您所描述的那样失败。

This seems to be a genuine bug. It works as expected on Linux and OpenBSD and fails as you describe on OS X.

舂唻埖巳落 2024-07-21 04:39:25

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

OSX 10.4.1, I can confirm the behaviour. The same code works fine (as long as timeout messages are fine) on Linux. All the evidence, including this - http://www.virtualbox.de/changeset/12347 - suggests that there is a real problem.

客…行舟 2024-07-21 04:39:25

是的,已知的错误。 我认为民意调查中断只是从 10.4 开始,我们必须在 Fink 中处理它。 Glib 的configure.in对此进行了测试,因此您可以确定这不是您的想象。 (嗯,不完全是这样,glib 在设备上测试 poll,而不是在 fifos 上。)

Yup, known bug. I think the poll breakage is only since 10.4, we had to deal with it in Fink. Glib's configure.in has a test for this, so you can be sure that you're not imagining it. (Well, not precisely this, glib tests for poll on devices, not fifos.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文