Non-blocking I / O behavior is strange for STDIN_FILENO and STDOUT_FILENO

I have the following code:

void
set_fl(int fd, int flags) /* flags are file status flags to turn on */
{
    int val;

    if ((val = fcntl(fd, F_GETFL, 0)) < 0)
        err_sys("fcntl F_GETFL error");

    val |= flags;       /* turn on flags */

    if (fcntl(fd, F_SETFL, val) < 0)
        err_sys("fcntl F_SETFL error");
}

int
main(void)
{
    char buf[BUFSIZ];
    set_fl(STDOUT_FILENO, O_NONBLOCK);  //set STDOUT_FILENO to nonblock
    if(read(STDIN_FILENO, buf, BUFSIZ)==-1) { //read from STDIN_FILENO
        printf("something went wrong with read()! %s\n", strerror(errno));
    }
}

      

As you can see, I set it STDOUT_FILENO

to non-blocking mode, but it seems that the read operation is not STDIN_FILENO

completed immediately. Why?

$ ./testprog
something went wrong with read()! Resource temporarily unavailable

      

thank

+3


source to share


1 answer


Correct: by making print calls errno

and perror

immediately after reading, to "busy resource" and error number 11, or EAGAIN/EWOULDBLOCK

as shown in this code:

#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>

int main (void) {
    char buf;

    fcntl (STDOUT_FILENO, F_SETFL, fcntl (STDOUT_FILENO, F_GETFL, 0) | O_NONBLOCK);
    fprintf (stderr, "%5d: ", errno); perror("");
    read (STDIN_FILENO, &buf, 1);
    fprintf (stderr, "%5d: ", errno); perror("");
}

      

which generates:

    0: Success
   11: Resource temporarily unavailable

      

The reason is that file descriptors are two different types of flags (see. Here in the section dealing with duplicate file descriptors):

You can duplicate a file descriptor or allocate a different file descriptor that refers to the same open file as the original. Duplicate descriptors share one file position and one set of file status flags (see File Status Flags), but each has its own set of file descriptor flags (see Descriptor Flags).



The first are the file descriptor flags , and they are really unique for each file descriptor. According to the documentation, FD_CLOEXEC

(close on exec

) is the only one currently in this camp.

All other flags are file status flags and are shared between files that have been duplicated. These include I / O modes such as O_NONBLOCK

.

So what happens here is that the standard output file descriptor is duplicated from standard input (order doesn't matter, just the fact that it is duplicated from another), so setting non-blocking mode on one affects all duplicates (and that, will probably include the standard error file descriptor, although I have not confirmed it).

It is generally not a good idea to guess in locking mode duplicate file descriptors and file descriptors that are likely to be inherited by subprocesses - these subprocesses do not always refer to their standard files in error (from their point of view).

If you want finer granular control over individual file descriptors, consider using them select

to validate the descriptors before trying to read.

+3


source







All Articles