Why does poll keep returning although there is no input?
Asked Answered
L

3

5

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.

Looker answered 4/9, 2013 at 14:35 Comment(1)
How do you expect to know when EOF appears else ?Discant
A
6

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.

Accused answered 4/9, 2013 at 14:49 Comment(4)
Thanks for the explanation. I expected EOF to be handled as if the file was blocked. I am trying the same with named pipes now (just one, actually (testa)) but now poll doesn't return at all, while echo a > testa does (when my program is running). Any idea?Looker
Yes, that's the point. read() from a named pipe will block until data is available. poll() should not return at all until your named pipe is readable, which happens when you echo a character into it.Accused
Yes, but this exactly doesn't happen. Even when I write data into the pipe, poll doesn't return. The echo a >> testa command returns (so I assume data was written to the pipe) but inside my program, poll doesn't return.Looker
Works perfectly for me... I just used your code, commented out testb and testc, mkfifo testa, run the program, and echo a >> testa. If your code is modified, post it. Also show ls -l test*.Accused
H
3

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.

Hardin answered 4/9, 2013 at 14:49 Comment(0)
R
2

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.

Rainarainah answered 4/9, 2013 at 14:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.