Почему опрос продолжает возвращаться, хотя нет данных?

Я написал небольшую тестовую программу, чтобы выяснить, как разговаривать с poll, Я создал три файла testa, testb, testc и написал строку hello\n к первому. Итак, вот мой призыв poll:

poll(polls.data(),polls.size(),-1)

Согласно manpage, время ожидания -1 должен указывать, что системный вызов никогда не прерывается. Тем не менее, он продолжает возвращаться, не имея ничего читать. Я всегда потребляю один байт ввода и вижу hello\n печатается, но опрос не останавливается там. Он просто продолжает притворяться, что есть что почитать.

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <sys/poll.h>
#include <unistd.h>
#include <errno.h>

#include <vector>
#include <map>
#include <string>
#include <iostream>

typedef int fd_t;

int main() {
  fd_t const a = open("testa",O_RDONLY);
  fd_t const b = open("testb",O_WRONLY);
  fd_t const c = open("testc",O_RDWR);
  std::map<fd_t,std::string> names{{{a,"testa"},{b,"testb"},{c,"testc"}}};

  std::vector<pollfd> polls;
  polls.push_back(pollfd{a, POLLIN, 0});
  polls.push_back(pollfd{b, 0, 0});
  polls.push_back(pollfd{c, POLLIN, 0});

  while (poll(polls.data(),polls.size(),-1)) {
    for (auto p : polls) {
      if ((p.revents & (POLLIN|POLLERR)) == POLLIN) {
        std::cout << "{" << p.fd << ", " << p.events << ", " << p.revents << "} ";
        char byte;
        auto const rr = read(p.fd,&byte,1);
        auto const en = errno;
        if (rr) {
          std::cout << "File " << names[p.fd] << " says something: '" << ((int)byte) << " (" << (((' '<byte) && (byte<127))?byte:'\0') << ")" << "' \n";
        } else {
          std::cout << "Strange (file " << names[p.fd] << "). errno says " << en << "\n";
        }
      }
    }
  }
}

Что я получаю, это:

{3, 1, 1} File testa says something: '104 (h)' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '101 (e)' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '108 (l)' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '108 (l)' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '111 (o)' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} File testa says something: '10 ()' 
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0
{3, 1, 1} Strange (file testa). errno says 0
{5, 1, 1} Strange (file testc). errno says 0

(повторяет последние две строки навсегда)

Я строю с g++ -Wall -Wextra -std=c++11 poll.cpp -o poll в ядре 3.10-2-amd64.

3 ответа

Решение

Условие EOF в обычном файле все еще доступно для чтения. Другими словами, ваш read() не будет блокировать Вот хороший список того, как разные реализации poll() реагировать на EOF в различных дескрипторах файлов: http://www.greenend.org.uk/rjk/tech/poll.html

Обратите внимание, что обычные файлы всегда возвращают POLLIN. Таким образом, вы должны проверить на EOF отдельно. На самом деле, опрос по обычному файлу ничего не делает для вас. Вам понадобятся сокеты или каналы или что-то еще, чтобы проверить ваш код.

Другие примечания: вы, вероятно, хотите проверить другие результаты в .revents, POLLERR, POLLHUP и POLLNVAL сигнализируют о различных состояниях ошибки и требуют специальной обработки.

Как только вы достигаете конца файла, он остается читаемым, так что poll вернется сразу, и звонит read немедленно вернет ноль. Вам нужно обработать это условие, возможно, закрыв его и удалив из набора опросов, где вы в данный момент печатаете Strange,

Локальные файловые дескрипторы всегда готовы к выполнению операций ввода-вывода (в отличие от сокетов, поскольку они зависят от внутреннего буфера ядра для ввода-вывода)). В вашем случае файловые дескрипторы всегда готовы к чтению, даже если они на самом деле пусты.

Другие вопросы по тегам