Consider this C program:
#include <poll.h>
#include <stdio.h>
#include <unistd.h>
#define TIMEOUT 500 // 0.5 s
#define BUF_SIZE 512
int fd_can_read(int fd, int timeout) {
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLIN;
if (poll(&pfd, 1, timeout)) {
if (pfd.revents & POLLIN) {
return 1;
}
}
return 0;
}
int main(int argv, char **argc) {
int fd;
size_t bytes_read;
char buffer[BUF_SIZE];
fd = STDIN_FILENO;
while (1) {
if (fd_can_read(fd, TIMEOUT)) {
printf("Can read\n");
bytes_read = read(fd, buffer, sizeof(buffer));
printf("Bytes read: %zu\n", bytes_read);
}
else {
printf("Can't read\n");
}
}
}
It tries to poll given file descriptor (which is the fd of stdin in this case), and tries to read from it when it's available for reading. Here's an example input file called "input":
stuff to be read
So let's say I run the program, give a few inputs and close it:
./a.out
test
Can read
Bytes read: 5
Can't read
Can't read
...
So lets try reading the input from a file by piping/redirecting the contents of it to stdin
of my program:
cat input | ./a.out # Or ./a.out < input
Bytes read: 0
Can read
Bytes read: 0
Can read
...
Now, the poll returns instantly (does not wait for the timeout to run out), and gives the results I was not expecting. I do know poll()
does not work on files correctly, but if I'm not mistaken, I'm not reading from a file.
The problem is that poll
(just like select
) only tell you that a call to e.g. read
will not block. It doesn't tell you if there's actually anything to read.
And if you read the read
manual page you will see that when it returns 0
it means end of file (or connection closed for sockets).
What poll
is telling you is that read
can be called without blocking, and what read
tells you by returning 0
is that there is nothing more to read.
You will get a similar "false positive" by pressing the end-of-file shortcut key (by default Ctrl-D on POSIX systems like Linux) for the non-piped or -redirected input example.