6

I would like to be able to tell if a character special file would block if a character were read from it without actually reading a character from it. Can this be done?

Charles Stewart
  • 502
  • 1
  • 5
  • 18
  • You will normally need to `open()` the file (though you don't need to `read()` from it). Will that be a problem? – Toby Speight Jun 15 '16 at 16:45
  • Just to clarify my earlier statement - you need an open *file descriptor* to perform this test. There's no kernel interface to do this with only the *file name* of the device. – Toby Speight Jun 15 '16 at 18:01

3 Answers3

7

POSIX allows non-blocking, zero-character reads which "may detect and return errors", including that the read would block:

  • open(2) the device in O_NONBLOCKing mode;
  • read(2) with a count of 0.

If this read operation checks for errors in such cases, if a read would block then read will return -1 and set errno to EAGAIN (or possibly EWOULDBLOCK for sockets, but you're asking about character devices).

Stephen Kitt
  • 411,918
  • 54
  • 1,065
  • 1,164
7

You can do this from bash using a 0 timeout to read.

if read -t 0
then read data
fi

To test a file descriptor other than stdin, say 3, use -u 3. To find how many chars are ready on stdin you can use a small perl script:

#!/usr/bin/perl
require 'sys/ioctl.ph';
$size = pack("L", 0);
ioctl(*STDIN, FIONREAD(), $size) or die "ioctl fail: $!\n";
$size = unpack("L", $size);
print "stdin ready: $size\n";
meuh
  • 49,672
  • 2
  • 52
  • 114
  • Is `read -t0` guaranteed not to read any characters from stdin, even if there is a line waiting? I don't find this behaviour documented on the bash or ksh manpages, although `reecho () { read -t1 LINE; echo $LINE; }; echo abcd | reecho` gives the behaviour consistent with what you descibe. – Charles Stewart Jun 15 '16 at 14:46
  • 3
    In my 4.3.42 version the man page says *If TIMEOUT is 0, read returns immediately, without trying to read any data,* – meuh Jun 15 '16 at 14:52
5

From C or C++ you would normally use pselect() to test if there is data ready for reading. You can do that without having to set the file descriptor mode to non-blocking.

Toby Speight
  • 8,460
  • 3
  • 26
  • 50
peterq
  • 76
  • 2
  • Note that you would set the timeout to 0 seconds and 0 microseconds to do this. I wondered at first if this meant "zero timeout" or "infinite timeout", but it appears that to get the latter, you pass NULL. – Nate Eldredge Jun 15 '16 at 16:24
  • 1
    Nice, I had `pselect()` firmly in the "multiplexing" part of my brain... – Stephen Kitt Jun 15 '16 at 16:32