I have a piece of software that is able to read commands from stdin for debug purposes in a separate thread. When my software runs as foreground process read
behaves as expected, its blocking and waits for input by the user, i.e the thread sleeps.
When the software is run as a background process, read
constantly returns 0
(possible EOF detected?).
The problem here is, that this specific read is in a while(true)
loop. It runs as fast as it can and steals precious CPU load on my embedded device.
I tried redirecting /dev/null
to the process but the behavior was the same. I am running my custom Linux on an ARM Cortex A5 board.
The problematic piece of code follows and is run inside its own thread:
char bufferUserInput[256]; const int sizeOfBuffer = SIZE_OF_ARRAY(bufferUserInput); while (1) { int n = read(0, bufferUserInput, sizeOfBuffer); //filedes = 0 equals to reading from stdin printf("n is: %dn", n); printf("Errno: %s",strerror(errno)); if (n == 1) { continue; } if ((1 < n) && (n < sizeOfBuffer) && ('n' == bufferUserInput[n - 1])) { printf("rn"); bufferUserInput[n - 1] = ''; ProcessUserInput(&bufferUserInput[0]); } else { n = 0; } }
I am looking for a way to prevent read
from constantly returning when running in the background and wait for user input (which of course will never come).
Advertisement
Answer
When stdin
is not a terminal, read
is returning with 0 because you are at the end of the file. read
only blocks after reading all available input when there could be more input in the future, which is considered to be possible for terminals, pipes, sockets, etc. but not for regular files nor for /dev/null
. (Yes, another process could make a regular file bigger, but that possibility isn’t considered in the specification for read
.)
Ignoring the various problems with your read loop that other people have pointed out (which you should fix anyway, as this will make reading debug commands from the user more reliable) the simplest change to your code that will fix the problem you’re having right now is: check on startup whether stdin is a terminal, and don’t launch the debug thread if it isn’t. You do that with the isatty
function, declared in unistd.h
.
#include <stdio.h> #include <unistd.h> // ... int main(void) { if (isatty(fileno(stdin))) start_debug_thread(); // ... }
(Depending on your usage context, it might also make sense to run the debug thread when stdin
is a pipe or a socket, but I would personally not bother, I would rely on ssh
to provide a remote (pseudo-)terminal when necessary.)