Question

I wrote a small test program to figure out how to talk to poll. I created three files testa,testb,testc and wrote the string hello\n to the first. So, here is my invocation of poll:

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

According to the manpage, a timeout of -1 should indicate that the syscall never times out. However, it keeps returning without having anything to read. I always consume one byte of the input and can see the hello\n being printed, but poll doesn't stop there. It just keeps on pretending there to be something to read.

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

What I get is this:

{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

(repeats the last two lines forever)

I'm building with g++ -Wall -Wextra -std=c++11 poll.cpp -o poll on the 3.10-2-amd64 kernel.

Was it helpful?

Solution

An EOF condition in a regular file is still readable. In other words, your read() won't block. Here's a nice list of how different implementations of poll() react to EOF in different sorts of file descriptors: http://www.greenend.org.uk/rjk/tech/poll.html

Note that regular files always return POLLIN. So you need to test for EOF separately. In fact, poll on a regular file doesn't do anything for you. You'll need sockets or pipes or something to test your code.

Other notes: you probably want to check for other results in .revents. POLLERR, POLLHUP, and POLLNVAL all signal different error conditions, and need special handling.

OTHER TIPS

Once you reach the end of a file, it remains readable so that poll will return immediately, and calling read will immediately return zero. You need to handle this condition, perhaps by closing it and removing it from the set of polls, where you're currently printing Strange.

The local file descriptors are always ready to perform I/O (unlike sockets, because they are depend on the kernel internal buffer for I/O)). In your case file descriptors are always ready for reading, even if they are empty actually.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top