Why does the survey keep coming back even though there is no input?

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

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

According to the man page, a timeout of -1 should indicate that syscall never expires. However, he keeps coming back with nothing to read. I always consume one input byte and see that hello\n is printed, but the polling does not stop. He just keeps pretending there is 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:

 {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 create with g++ -Wall -Wextra -std=c++11 poll.cpp -o poll in the kernel 3.10-2-amd64.

+4
source share
3 answers

The EOF clause in the regular file is still readable. In other words, your read() will not block. Here is a good list of how various poll() implementations respond to EOF in different types of file descriptors: http://www.greenend.org.uk/rjk/tech/poll.html

Note that regular files always return POLLIN. Therefore, you need to check the EOF separately. In fact, polling in a regular file does nothing for you. You will need sockets or pipes or something to check your code.

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

+4
source

Local file descriptors are always ready to do I / O (unlike sockets, because they depend on the internal kernel buffer for I / O). In your case, file descriptors are always ready to be read, even if they are empty.

+2
source

Once you get to the end of the file, it will remain readable, so the poll will return immediately, and the read call will immediately return zero. You need to handle this condition, possibly closing it and removing it from the survey set where you are currently printing Strange .

+2
source

Source: https://habr.com/ru/post/1500558/


All Articles