Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to check if stdin is still opened without blocking?

I need my program written in pure C to stop execution when stdin is closed.

There is indefinite work done in program main cycle, and there is no way I can use blocking checks (like getc()) there (no data is supposed to arrive on stdin - it just stays opened for unknown time).

I intend to use described functionality in realization of network daemon hosted in inetd, xinetd or their analogs - it should emit data on stdout while connection stays opened and correctly finish work when it closes. Now my program is killed by hosting service as it won't stop after connection termination.

I wonder if fctntl() with O_NONBLOCK flag applied to stdin descriptor would allow me to use read() function in non-blocking mode? Should I use select() somehow?

P.S. The data is not supposed but might arrive to stdin. A way of non-blocking readout woould be an answer for the question.

like image 833
Basilevs Avatar asked Oct 20 '09 12:10

Basilevs


People also ask

What happens if you close stdin?

It does not "inhibit input". close(fileno(stdin)) causes any further attempts at input from stdin , after the current buffer has been depleted, to fail with EBADF , but only until you open another file, in which case that file will become fd #0 and bad things will happen.

Is stdin buffered?

stdin is buffered (line buffering doesn't affect stdin) stdout is buffered (line buffered if connected to a terminal) stderr is unbuffered.

Does Getchar read stdin?

getchar is a function in C programming language that reads a single character from the standard input stream stdin, regardless of what it is, and returns it to the program. It is specified in ANSI-C and is the most basic input function in C. It is included in the stdio. h header file.

Is there a limit to stdin?

stdin has no limits on length or speed. If you want to get gigabytes of data via stdin you can, and your computer will supply it as fast as it can.


3 Answers

select() does exactly what you want: signal that an operation (read, in this case) on a file descriptor (file, socket, whatever) will not block.

#include <stdio.h>
#include <sys/select.h>

int is_ready(int fd) {
    fd_set fdset;
    struct timeval timeout;
    int ret;
    FD_ZERO(&fdset);
    FD_SET(fd, &fdset);
    timeout.tv_sec = 0;
    timeout.tv_usec = 1;
    //int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
     struct timeval *timeout);
    return select(fd+1, &fdset, NULL, NULL, &timeout) == 1 ? 1 : 0;
}

You can now check a file descriptor before use, for instance in order to empty the file descriptor:

void empty_fd(int fd) {
    char buffer[1024];
    while (is_ready(fd)) {
        read(fd, buffer, sizeof(buffer));
    }
}

In your case, use fileno(stdin) to get the file descriptor of stdin:

if (is_ready(fileno(stdin))) {
    /* read stuff from stdin will not block */
}
like image 173
digitalarbeiter Avatar answered Sep 19 '22 17:09

digitalarbeiter


I wonder if fctntl() with O_NONBLOCK flag applied to stdin descriptor would allow me to use read() function in non-blocking mode?

Running stdin with O_NONBLOCK has advantages over select. Select says that there is some data, but not how much. There are times that you want to get all available data, but not block, regardless of how much in in the queue. Running select for each character seems like a lot of busy work... O_NONBLOCK did not work for me. It is an internal flag, not exposed in most tty drivers.

Check out ioctl(..., FIONBIO). It seems to get the job done.

like image 37
fbp Avatar answered Sep 20 '22 17:09

fbp


I'm not sure whether you can set O_NONBLOCK on stdin, but select() or poll() will definitely get the job done.

like image 23
Michael Foukarakis Avatar answered Sep 21 '22 17:09

Michael Foukarakis