52

I have a fd descriptor, which I can use to read from by calling read(fd, buffer,...). Now, I want to check if there is anything to read before actually making the call, because the call is blocking. How do I do this?

mu is too short
  • 426,620
  • 70
  • 833
  • 800
ABCD
  • 7,914
  • 9
  • 54
  • 90
  • 3
    The behavior of read with respect to blocking varies depending on the descriptor type. To what type of device does `fd` refer? – kqnr Apr 11 '11 at 01:59
  • standard inputs, right now, it's blocking – ABCD Apr 11 '11 at 02:00
  • 1
    @KenRockot so if I have a regular file it is different than for example fd which is a socketDescriptor ? – Bionix1441 Apr 19 '16 at 17:18

6 Answers6

75
int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

The code snippet above will configure such a descriptor for non-blocking access. If data is not available when you call read, then the system call will fail with a return value of -1 and errno is set to EAGAIN. See the fcntl man pages for more information.

Alternatively, you can use select with a configurable timeout to check and/or wait a specified time interval for more data. This method is probably what you want and can be much more efficient.

Kleist
  • 7,785
  • 1
  • 26
  • 30
Judge Maygarden
  • 26,961
  • 9
  • 82
  • 99
  • 1
    And then check for -1 returns from `read` and that `errno` is `EAGAIN`. – mu is too short Apr 11 '11 at 02:06
  • good doc about file with non-blocking support setting errno at [opengroup](http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html) – droid192 Jul 04 '16 at 16:11
  • 10
    This is NOT the correct answer. O_NONBLOCK against a regular fs has no effect (read() will keep blocking) and select() will always erroneously report the fd as "ready". Reliable non-blocking IO for regular files on Linux is basically (and unfortunately) not supported. – Giampaolo Rodolà Dec 19 '16 at 12:14
  • 5
    [Some](http://www.linux-mag.com/id/308/) [good](https://www.remlab.net/op/nonblock.shtml) [sources](http://neugierig.org/software/blog/2011/12/nonblocking-disk-io.html) on regular files and non-blocking I/O. However, if `fd` is stdin, then it seems harmless to let `O_NONBLOCK` speed things up when reading from a terminal/pipe and do nothing when reading from a file. – Paul A Jungwirth May 06 '17 at 07:07
18

Use select or poll to query whether the file descriptor has data available for read:

fd_set fds;
FD_ZERO(&fds);
FD_SET(&fds, fd);
if (select(fd+1, &fds, 0, 0)==1) /* there is data available */
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
3

Depending on what you're doing you might be able to turn the problem inside out and use select to tell you when your file descriptor has something to read.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
2

use poll for timeout:

struct pollfd p;
int n;
while ((n = poll(&p, 1, iTo)) < 0) 
{
    if (errno == EAGAIN || errno == EINTR)
       continue;
}

if (!n) {
    errno = ETIMEDOUT;
}

while ((len = read(Fd, anyBuff, sizeof(anyenter code hereBuff))) < 0) {
    if (errno == EAGAIN || errno == EINTR)
        continue;
}
YCN-
  • 203
  • 2
  • 12
Ankur Soni
  • 21
  • 1
1

Check out the API or system/tool you are using for your specific programming purpose. (descriptors/file descriptors have many uses in Linux programming such as socket programming, file manipulation, shared_memory, etc.)

For example one time I used inotify (for monitoring file system events). This API gives you ability to create non-blocking file from the first point and there's no need to use fcntl or such APIs to modify the created file descriptor.

Probably other tools or API's that you're going to use have such functionality and you can set such option in their initiation or such steps (check this first).

But generally yes using fcntl is the answer and it might be interesting to know that inotify itself uses fcntl itself too. (refer to the manual pages of Linux)

select() can give you a same functionality as it operates on file descriptors for monitoring events with a specified limited time but keep in mind that the main usage of select is for monitoring multiple file descriptors.

Novin Shahroudi
  • 620
  • 8
  • 18
1

I think you should use select or poll functions to check if there are something to read from the descriptor.

Elalfer
  • 5,312
  • 20
  • 25