当其他进程关闭fifo时,无法从epoll_wait唤醒

时间:2012-10-26 15:14:23

标签: linux select multiprocessing fifo epoll

我在两个不同的二进制文件中看到了不同的epollselect行为,并希望得到一些调试帮助。在下文中,epoll_waitselect将互换使用。

我有两个进程,一个作者和一个阅读器,通过fifo进行通信。读者执行epoll_wait以获得写入通知。我还想知道作家何时关闭了fifo,epoll_wait似乎也应该通知我。以下玩具程序的行为符合预期,说明了我正在努力实现的目标:

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/stat.h>
#include <unistd.h>

int
main(int argc, char** argv)
{
  const char* filename = "tempfile";
  char buf[1024];
  memset(buf, 0, sizeof(buf));

  struct stat statbuf;
  if (!stat(filename, &statbuf))
    unlink(filename);

  mkfifo(filename, S_IRUSR | S_IWUSR);

  pid_t pid = fork();
  if (!pid) {
    int fd = open(filename, O_WRONLY);
    printf("Opened %d for writing\n", fd);
    sleep(3);
    close(fd);
  } else {
    int fd = open(filename, O_RDONLY);
    printf("Opened %d for reading\n", fd);

    static const int MAX_LENGTH = 1;
    struct epoll_event init;
    struct epoll_event evs[MAX_LENGTH];
    int efd = epoll_create(MAX_LENGTH);

    int i;
    for (i = 0; i < MAX_LENGTH; ++i) {
        init.data.u64 = 0;
        init.data.fd = fd;
        init.events |= EPOLLIN | EPOLLPRI | EPOLLHUP;
        epoll_ctl(efd, EPOLL_CTL_ADD, fd, &init);
    }

    while (1) {
      int nfds = epoll_wait(efd, evs, MAX_LENGTH, -1);
      printf("%d fds ready\n", nfds);
      int nread = read(fd, buf, sizeof(buf));
      if (nread < 0) {
        perror("read");
        exit(1);
      } else if (!nread) {
        printf("Child %d closed the pipe\n", pid);
        break;
      }
      printf("Reading: %s\n", buf);
    }
  }
  return 0;
}

然而,当我与另一个读者(其代码我没有特权发布,但是它完全相同的调用 - 玩具程序是以它为模型)这样做时,当作者关闭时,进程不会唤醒fifo。玩具阅读器还提供了select所需的语义。配置为使用select的真实阅读器也会失败。

什么可能解释两者的不同行为?对于任何提供的假设,我如何验证它们?我正在运行Linux 2.6.38.8。

1 个答案:

答案 0 :(得分:0)

strace是一个很好的工具,可以确认系统调用是否被正确调用(即参数传递正确并且不会返回任何意外错误)。

除此之外,我建议使用lsof检查没有其他进程仍然打开该FIFO。