Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
213 views
in Technique[技术] by (71.8m points)

c++ - Why does poll keep returning although there is no input?

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 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 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:'') << ")" << "' 
";
        } else {
          std::cout << "Strange (file " << names[p.fd] << "). errno says " << en << "
";
        }
      }
    }
  }
}

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...