How to check if stdin is still opened without blocking?

后端 未结 5 540
野性不改
野性不改 2021-01-02 00:57

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 blocki

相关标签:
5条回答
  • 2021-01-02 01:24

    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.

    0 讨论(0)
  • 2021-01-02 01:27

    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 */
    }
    
    0 讨论(0)
  • 2021-01-02 01:40

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

    0 讨论(0)
  • 2021-01-02 01:44

    What's wrong with feof(stdin) ?

    0 讨论(0)
  • 2021-01-02 01:45

    Yes, you can use select (with a zero timeout). You don't need to set the file descriptor non-blocking, though - if select tells you that the file descriptor is readable, then a read on it will definitely not block.

    So, poll file descriptor 0 occaisionally with select, and if it's readable, read it. If read returns 0, then that means it's been closed.

    0 讨论(0)
提交回复
热议问题