Why does poll keep returning although there is no input?
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.
use poll() timeout only for new data on socket
Probably been answered in the linked posts, but the basic idea is that the poll
, select
, and other mechanisms do not tell you when there is new data on the socket. As you mention correctly, they only tell you when a read()
would not block.
You may use EPOLLET
with Linux's epoll(7)
interface (other systems might have other equivalents) to do what you want; however keep in mind this is not portable.
The correct and accepted design is to either consume the network buffer fully, keep partial messages in a application-defined buffer (i.e. not in the socket's buffer) and keep track of how much additional data you need to read from the network.
Poll works on stdin when entering manually, but not when input is piped and not redirected
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.
Why poll() returns immediately on regular files and blocks on fifo?
poll()
or select()
never block on regular files. They always return a regular file as "ready". If you want to use poll()
to do what tail -f
does, you're on the wrong track.
Quoting from the SUSv4 standard:
The
poll()
function shall support regular files, terminal and
pseudo-terminal devices, FIFOs, pipes, sockets and[OB XSR]
STREAMS-based files. The behavior ofpoll()
on
elements of fds that refer to other types of file is unspecified.Regular files shall always poll TRUE for reading and writing.
Since using poll()
or select()
on regular files is pretty much useless, newer interfaces have tried to remedy that. On BSD, you could use kqueue(2)
with EVFILT_READ
, and on Linux inotify(2)
with IN_MODIFY
. The newer epoll(7)
interface on Linux will simply error out with EPERM
if you try to watch a regular file.
Unfortunately, neither of those is standard.
Why in this case the stdin fd is not ready
Polling works at the file descriptor level while fscanf
works at the higher file handle level.
At the higher level, the C runtime library is free to cache the input stream in such a way that it would affect what you can see at the lower level.
For example (and this is probably what's happening here), the first time you fscanf
your word aa
, the entire line is read from the file descriptor and cached, before that first word is handed back to you.
A subsequent fscanf
(with no intervening poll
) would first check the cache to get the next word and, if it weren't there, it would go back to the file descriptor to get more input.
Unfortunately, the fact that you're checking for a poll event before doing this is causing problems. As far as the file descriptor level goes, the entire line has been read by your first fscanf
so no further input is available - poll
will therefore wait until such information does become available.
You can see this in action if you change:
n = fscanf(stdin, "%s", buffer);
into:
n = read(STDIN_FILENO, buffer, 3);
and change the printf
to:
printf("data from stdin: %*.*s\n", n, n, buffer);
In that case, you do get the output you expect as soon as you press the ENTER key:
data from stdin: aa
data from stdin: bb
data from stdin: cc
data from stdin: dd
Just keep in mind that sample code is reading up to three characters (like aa<space>
) rather than a word. It's more to illustrate what the problem is rather than give you the solution (to match your question "Can you explain why this happens?").
The solution is not to mix descriptor and handle based I/O when the caching of the latter can affect the former.
How can a C program poll for user input while simultaneously performing other actions in a Linux environment?
Your task requires an event loop based on select
or epoll
. One event it would wait for is user input - when STDIN_FILENO
becomes ready for read. Another is the 1-second periodic timer when you need to poll the controller.
There are quite a few libraries that implement an event loop for you so that you can focus on what events you need to handle and how. libevent
is one of the oldest, feature rich and popular.
Related Topics
Long Long Int VS. Long Int VS. Int64_T in C++
Why Are Python Programs Often Slower Than the Equivalent Program Written in C or C++
Class Template with Template Class Friend, What's Really Going on Here
Trivial VS. Standard Layout VS. Pod
Prevent Class Inheritance in C++
Boost Spirit Semantic Action Parameters
How to Evaluate Mathematical Expressions in C++
How to Take Screenshots of a Window with C++ in Windows
Emulate "Double" Using 2 "Float"S
Is It Safe to Fork from Within a Thread
Why Isn't 'Int Pow(Int Base, Int Exponent)' in the Standard C++ Libraries
Std::Transform() and Toupper(), No Matching Function
Why Does Std::Move Prevent Rvo (Return Value Optimization)
C++11 Stl Containers and Thread Safety
What Is Value of Eof and '\0' in C
Should I Unify Two Similar Kernels with an 'If' Statement, Risking Performance Loss