Skip to content
Advertisement

Prevent read() systemcall returing with 0 when run as background process

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.)

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement