Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When non-blocking I/O is turned on for stdout, is it correct for the OS to turn it on for stdin too?

Tags:

c

linux

posix

macos

I have noticed some unexpected behaviour on both OS X and Linux. Turning on non-blocking I/O (using O_NONBLOCK) for standard output turns it on for standard input too!

Are these OSes behaving correctly? If so, is this behaviour defined by POSIX? Please point me to the relevant documentation if this is the case.

Here's a example program I used to test this:

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

int main (int argc, char *argv[]) {
  int flags = fcntl(STDOUT_FILENO, F_GETFL);
  if (argc > 1 && strcmp(argv[1], "1") == 0) {
    fcntl(STDOUT_FILENO, F_SETFL, flags | O_NONBLOCK);
  }
  printf("stdout O_NONBLOCK is: %d\n", fcntl(STDOUT_FILENO, F_GETFL) & O_NONBLOCK);
  printf("stdin O_NONBLOCK is: %d\n", fcntl(STDIN_FILENO, F_GETFL) & O_NONBLOCK);
  return 0;
}

On OS X:

$ clang -o fd-test fd-test.c
$ ./fd-test
stdout O_NONBLOCK is: 0
stdin O_NONBLOCK is: 0
$ ./fd-test 1
stdout O_NONBLOCK is: 4
stdin O_NONBLOCK is: 4

On Linux:

$ gcc -o fd-test fd-test.c
$ ./fd-test
stdout O_NONBLOCK is: 0
stdin O_NONBLOCK is: 0
$ ./fd-test 1
stdout O_NONBLOCK is: 2048
stdin O_NONBLOCK is: 2048
like image 582
Chaitanya Gupta Avatar asked May 26 '14 08:05

Chaitanya Gupta


People also ask

What is stdin stdout?

stdin − It stands for standard input, and is used for taking text as an input. stdout − It stands for standard output, and is used to text output of any command you type in the terminal, and then that output is stored in the stdout stream.

What are the differences between a blocking I/O and a non-blocking IO?

Well blocking IO means that a given thread cannot do anything more until the IO is fully received (in the case of sockets this wait could be a long time). Non-blocking IO means an IO request is queued straight away and the function returns. The actual IO is then processed at some later point by the kernel.

How does non-blocking IO works?

Non-blocking IO under the hood Most non-blocking frameworks use an infinite loop that constantly checks (polls) if data is returned from IO. This is often called the event loop. An event loop is literally a while(true) loop that in each iteration will check if data is ready to read from a network socket.

Is stdout blocked?

stdout are unlike other streams in Node in that writes to them are usually blocking. They are blocking in the case that they refer to regular files or TTY file descriptors. In the case they refer to pipes, they are non-blocking like other streams".


1 Answers

When a process is started from the shell, stdin, stdout and stderr point to the same file description. This file description is marked as O_NONBLOCK by your fcntl(1) call and therefore expectedly both file descriptors are marked as O_NONBLOCK.

If you want to indeed write to the same file from two file descriptors but want one to be marked as O_NONBLOCK, you need to create a new file description for the same file. If you know the file name of the file in question, you can achieve this by simply calling open() with the desired file name and flags. On some operating systems, you can find the file name using a platform-specific API, such as the /proc/fd virtual file system (many Unices including Linux) or the fd2path() function from Plan 9. Refer to this question for more details.

Note that simply calling open("/dev/fd/0", ...) may not work as intended as it returns a pointer to the same file description on some platforms if I recall correctly.

like image 97
fuz Avatar answered Oct 10 '22 07:10

fuz